Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -301,13 +301,6 @@ requirements.txt: pyproject.toml
# a PyPI entry; also print out CVE description and potential fixes if audit
# found an issue. If an advisory needs to be ignored, use the --ignore-vuln option.
#
# Remove GHSA-vfmq-68hx-4jfw when the following issue is resolved to be able to
# install the latest version of lxml.
# https://github.com/semgrep/semgrep/issues/11630
#
# Remove PYSEC-2026-2132 when Semgrep allows Click >=8.3.3. Click is a
# transitive dependency of Semgrep
#
# GHSA-hvrp-rf83-w775 ignore-vuln GHSA-jpw9-pfvf-9f58, and ignore-vuln GHSA-vj7q-gjh5-988w are advisories
# for the mcp package, which is a dependency of semgrep and we cannot update it outselves. Macaron does
# not use this transitive dependency and we can ignore them for now. Remove them when semgrep is updated and uses
Expand All @@ -319,8 +312,7 @@ audit:
echo "No package pip_audit installed, upgrade your environment!" && exit 1; \
fi;
python -m pip_audit --skip-editable --desc on --fix --dry-run \
--ignore-vuln GHSA-vfmq-68hx-4jfw --ignore-vuln PYSEC-2026-2132 --ignore-vuln GHSA-hvrp-rf83-w775 \
--ignore-vuln GHSA-jpw9-pfvf-9f58 --ignore-vuln GHSA-vj7q-gjh5-988w
--ignore-vuln GHSA-hvrp-rf83-w775 --ignore-vuln GHSA-jpw9-pfvf-9f58 --ignore-vuln GHSA-vj7q-gjh5-988w

# Run some or all checks over the package code base.
.PHONY: check check-code check-ruff check-lint check-mypy check-go check-actionlint
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ dependencies = [
"beautifulsoup4 >=4.12.0,<5.0.0",
"problog >=2.2.6,<3.0.0",
"cryptography >=48.0.1,<49.0.0",
"semgrep == 1.151.0",
"semgrep == 1.171.0",
"email-validator >=2.2.0,<3.0.0",
"rich >=13.5.3,<15.0.0",
"lark >=1.3.0,<2.0.0",
Expand Down
41 changes: 21 additions & 20 deletions src/macaron/policy_engine/policy_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,20 @@ def get_generated(database_path: os.PathLike | str) -> SouffleProgram:

metadata = MetaData()
engine = create_engine(f"sqlite:///{database_path}", echo=False)
metadata.reflect(engine)
try:
metadata.reflect(engine)

prelude = get_souffle_import_prelude(os.path.abspath(database_path), metadata)
prelude = get_souffle_import_prelude(os.path.abspath(database_path), metadata)

for table_name in metadata.tables:
table = metadata.tables[table_name]
if table_name[0] == "_":
prelude.update(project_table_to_key(f"{table_name[1:]}_attribute", table))
prelude.update(project_with_fk_join(table))
for table_name in metadata.tables:
table = metadata.tables[table_name]
if table_name[0] == "_":
prelude.update(project_table_to_key(f"{table_name[1:]}_attribute", table))
prelude.update(project_with_fk_join(table))

return prelude
return prelude
finally:
engine.dispose()


def copy_prelude(
Expand Down Expand Up @@ -130,18 +133,16 @@ def _check_version(database_path: str) -> None:
The path to the macaron database
"""
engine = create_engine(f"sqlite:///{database_path}", echo=False)

with engine.connect() as conn:
versions = conn.execute(
select(Analysis.macaron_version).where(Analysis.macaron_version != mcn_version)
).scalar()
if versions is not None:
logger.error("Database generated with unsupported versions (%s).", versions)
logger.error(
"Only databases generated by Macaron version %s are supported.",
mcn_version,
)
sys.exit(os.EX_DATAERR)
try:
with engine.connect() as conn:
versions = conn.execute(
select(Analysis.macaron_version).where(Analysis.macaron_version != mcn_version)
).scalar()
if versions is not None:
logger.error("Database generated with unsupported versions (%s).", versions)
sys.exit(os.EX_DATAERR)
finally:
engine.dispose()


def show_prelude(database_path: str) -> None:
Expand Down
2 changes: 2 additions & 0 deletions tests/build_spec_generator/test_macaron_db_extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def macaron_db_session() -> Generator[Session, Any, None]:
yield session

session.close()
engine.dispose()


@pytest.fixture()
Expand All @@ -64,6 +65,7 @@ def invalid_db_session() -> Generator[Session, Any, None]:
yield session

session.close()
engine.dispose()


@pytest.mark.parametrize(
Expand Down
7 changes: 5 additions & 2 deletions tests/database/test_database_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import os
import sqlite3
from collections.abc import Iterable
from contextlib import closing
from pathlib import Path

import pytest
Expand Down Expand Up @@ -37,11 +38,13 @@ def db_man() -> Iterable:
"""Set up the database and ensure it is empty."""
db_manager = DatabaseManager(DB_PATH, base=Base)
con = sqlite3.connect(DB_PATH)
with con:
with closing(con), con:
Comment on lines 40 to +41

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, you’re not using pylint’s code-style checker so you didn’t get the tip to change these into

with closing(con := sqlite3.connect(DB_PATH)), con:
    ...

con.execute("drop table if exists _test_orm_table;")
con.execute("drop view if exists test_orm_table;")
con.commit()

yield db_manager
db_manager.engine.dispose()
os.remove(DB_PATH)


Expand All @@ -66,7 +69,7 @@ def test_orm_mapping(

query = "select * from _test_orm_table;"
con = sqlite3.connect(DB_PATH)
with con:
with closing(con), con:
cursor = con.execute(query)
rows = cursor.fetchall()
assert (str(rows) == str([(identifier, test_value)])) == expect
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2025 - 2025, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2025 - 2026, Oracle and/or its affiliates. All rights reserved.
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/.

"""This module contains tests for the GitHub Actions vulnerabilities check."""
Expand Down Expand Up @@ -58,6 +58,7 @@ def test_github_actions_vulns(
httpserver: HTTPServer,
tmp_path: Path,
macaron_path: Path,
monkeypatch: pytest.MonkeyPatch,
ci_name: str,
ci_services: dict[str, BaseCIService],
expected: str,
Expand Down Expand Up @@ -96,6 +97,10 @@ def test_github_actions_vulns(
httpserver.expect_request("/v1/query").respond_with_json(query_json)
httpserver.expect_request("/v1/querybatch").respond_with_json(query_batch_json)

# Keep the test offline: resolving a mutable GitHub Action ref otherwise
# issues a live GitHub API request and can block on rate-limit backoff.
monkeypatch.setattr(ci_services["github_actions"].api_client, "get_commit_sha_from_ref", lambda *_: None)

ctx.dynamic_data["ci_services"] = [get_ci_info(ci_services, ci_name, gha_source_path)]

assert check.run_check(ctx).result_type == expected
Loading