Skip to content

Conversation

@Demolus13
Copy link
Member

@Demolus13 Demolus13 commented Sep 28, 2025

Summary

This Pull Request introduces a new --existing-policy flag to the verify-policy command, allowing users to run example policies by name without specifying a file path. It also adds support for policy templates.

The new --existing-policy (-e) flag executes a predefined policy template by name. If the template exists, it populates the <PACKAGE_PURL> placeholder with the value from the --package-url (-purl) argument and runs the policy. If the template name is not found, it lists all available templates.

Example policies

  1. A malware detection policy for the package (based on the malware detection tutorial)
macaron analyze -purl pkg:pypi/[email protected]
macaron verify-policy --database output/macaron.db --existing-policy malware-detection -purl pkg:pypi/django
  1. A malware detection policy for the package and all its dependencies (based on the malware detection tutorial)
python3.11 -m venv /tmp/.django_venv
/tmp/.django_venv/bin/pip install django==5.0.6
macaron analyze -purl pkg:pypi/[email protected] --python-venv "/tmp/.django_venv" --deps-depth=1  
macaron verify-policy --database output/macaron.db --existing-policy malware-detection-dependencies -purl pkg:pypi/django
  1. Analyzing GitHub Actions (tutorial)
macaron analyze -purl pkg:maven/org.apache.logging.log4j/[email protected]
macaron verify-policy --database output/macaron.db --existing-policy check-github-actions -purl pkg:maven/org.apache.logging.log4j/log4j-core

Description of changes

  • Added a --existing-policy (-e) argument to the verify-policy CLI command, enabling users to select and run example policies from the built-in resources.
  • Updated the policy loading logic to support both file-based and named example policies. If a policy name is provided, the command loads the corresponding template from the resources/policies/datalog directory.
  • Added support for the --package-url (-purl) argument to substitute the <PACKAGE_PURL> placeholder in policy templates.
  • Added new example policy templates for common use cases.
  • Added new test cases for --existing-policy (-e) flag in tests/policy_engine/test_existing_policy.py

Related issues

N/A

Checklist

  • I have reviewed the contribution guide.
  • My PR title and commits follow the Conventional Commits convention.
  • My commits include the "Signed-off-by" line.
  • I have signed my commits following the instructions provided by GitHub. Note that we run GitHub's commit verification tool to check the commit signatures. A green verified label should appear next to all of your commits on GitHub.
  • I have updated the relevant documentation, if applicable.
  • I have tested my changes and verified they work as expected.

@oracle-contributor-agreement oracle-contributor-agreement bot added the OCA Verified All contributors have signed the Oracle Contributor Agreement. label Sep 28, 2025
@Demolus13 Demolus13 self-assigned this Sep 28, 2025
@Demolus13 Demolus13 force-pushed the pgovale/example-policies branch from 30b51e3 to ce3dfd5 Compare October 7, 2025 06:22
Copy link
Member

@behnazh-w behnazh-w left a comment

Choose a reason for hiding this comment

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

Please add a unit test to tests/policy_engine/test_policy.py. Also add an integration test.

policy_content = file.read()
elif verify_policy_args.policy:
policy_dir = os.path.join(macaron.MACARON_PATH, "resources/policies/datalog")
available_policies = [policy[:-12] for policy in os.listdir(policy_dir) if policy.endswith(".dl.template")]
Copy link
Member

Choose a reason for hiding this comment

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

It would be good to avoid hardcoding [:-12].

Suggested change
available_policies = [policy[:-12] for policy in os.listdir(policy_dir) if policy.endswith(".dl.template")]
policy_suffix = ".dl.template"
available_policies = [
os.path.splitext(policy)[0].replace(policy_suffix, "")
for policy in os.listdir(policy_dir)
if policy.endswith(policy_suffix)
]

policy_path = os.path.join(policy_dir, f"{verify_policy_args.policy}.dl.template")
with open(policy_path, encoding="utf-8") as file:
policy_content = file.read()
if verify_policy_args.package_url:
Copy link
Member

Choose a reason for hiding this comment

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

Let's check that the PURL using the packageurl library, which is already a dependency of Macaron:

try:
    PackageURL.from_string(verify_policy_args.package_url)
except ValueError as error:
    logger.error("The package url %s is not valid.", verify_policy_args.package_url)
    return os.EX_USAGE

@behnazh-w behnazh-w marked this pull request as ready for review October 30, 2025 06:55
@Demolus13 Demolus13 force-pushed the pgovale/example-policies branch 2 times, most recently from ae722e9 to a2203de Compare October 31, 2025 06:55
@Demolus13 Demolus13 changed the title feat: add --policy flag in verify-policy command for example policies feat: add --existing-policy flag in verify-policy command for example policies Nov 1, 2025
@Demolus13 Demolus13 force-pushed the pgovale/example-policies branch from 40dbe23 to ff9fff7 Compare November 4, 2025 04:36

apply_policy_to("check-dependencies", component_id) :-
is_component(component_id, purl),
match("<PACKAGE_PURL>@.*", purl).
Copy link
Member

Choose a reason for hiding this comment

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

What if the user provides a PURL that contains version as well? Then the policy won't match the PURL.

Copy link
Member Author

Choose a reason for hiding this comment

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

Does removing @.* resolve the issue?

from

match("<PACKAGE_PURL>@.*", purl).

to

match("<PACKAGE_PURL>", purl).

Copy link
Member

Choose a reason for hiding this comment

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

Yes, but that would mean we can't use wildcards, which are useful for creating more generic policies that apply to all versions. Alternatively, we could allow the wildcard within the PURL argument itself 🤔

Copy link
Member

@behnazh-w behnazh-w left a comment

Choose a reason for hiding this comment

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

I suggest we add a --list-policies option to verify-policy, allowing users to easily see and choose from the available policies. We should also update the tutorial to include this new option. Additionally, we can provide a description file for each template policy and display that information when the command is used. To ensure consistency, let’s add a unit test that verifies every template policy has an associated description file.

@@ -0,0 +1,53 @@
==============================================================
Verify with an existing example policy using --existing-policy
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Verify with an existing example policy using --existing-policy
How to use the policy engine to verify with our predefined policies

Verify with an existing example policy using --existing-policy
==============================================================

This short tutorial shows how to use the ``--existing-policy`` flag with the ``verify-policy`` subcommand to run one of the example (predefined) policies that ship with Macaron.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
This short tutorial shows how to use the ``--existing-policy`` flag with the ``verify-policy`` subcommand to run one of the example (predefined) policies that ship with Macaron.
This tutorial shows how to use the ``--existing-policy`` flag with the ``verify-policy`` subcommand to run one of the predefined policies that ship with Macaron.

Use case
--------

Use ``--existing-policy`` when you want to run one of the built-in example policies by name instead of providing a local policy file with ``--file``. Example policies are useful for quick checks or automated examples/tests.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Use ``--existing-policy`` when you want to run one of the built-in example policies by name instead of providing a local policy file with ``--file``. Example policies are useful for quick checks or automated examples/tests.
Use ``--existing-policy`` when you want to run one of the built-in policies by name instead of providing a local policy file with ``--file``. Pre-defined policies are useful for quick checks or automated examples/tests.

Example
-------

Run the ``malware-detection`` example policy against a package URL:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Run the ``malware-detection`` example policy against a package URL:
Run the ``malware-detection`` policy against a package URL:

./run_macaron.sh verify-policy \
--database output/macaron.db \
--existing-policy malware-detection \
--package-url "pkg:pypi/django"
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
--package-url "pkg:pypi/django"
--package-url pkg:pypi/django@.*


def test_verify_existing_policy_not_found(tmp_path: Path) -> None:
"""Requesting a non-existent policy returns usage error."""
db_file = tmp_path / "macaron.db"
Copy link
Member

Choose a reason for hiding this comment

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

Please use os.path.join for constructing paths to be consistent with the rest of the codebase.


def test_verify_existing_policy_success(tmp_path: Path) -> None:
"""When an existing policy is provided and package-url is valid, verify_policy returns EX_OK."""
db_file = tmp_path / "macaron.db"
Copy link
Member

Choose a reason for hiding this comment

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

Please use os.path.join for constructing paths to be consistent with the rest of the codebase.


apply_policy_to("github_actions_vulns", component_id) :-
is_component(component_id, purl),
match("<PACKAGE_PURL>*", purl).
Copy link
Member

Choose a reason for hiding this comment

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

Based on our discussion, this should change to

Suggested change
match("<PACKAGE_PURL>*", purl).
match("<PACKAGE_PURL>", purl).


apply_policy_to("check-dependencies", component_id) :-
is_component(component_id, purl),
match("<PACKAGE_PURL>*", purl).
Copy link
Member

Choose a reason for hiding this comment

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

Based on our discussion, this should change to

Suggested change
match("<PACKAGE_PURL>*", purl).
match("<PACKAGE_PURL>", purl).


apply_policy_to("check-component", component_id) :-
is_component(component_id, purl),
match("<PACKAGE_PURL>*", purl).
Copy link
Member

Choose a reason for hiding this comment

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

Based on our discussion, this should change to

Suggested change
match("<PACKAGE_PURL>*", purl).
match("<PACKAGE_PURL>", purl).

#include "prelude.dl"

Policy("github_actions_vulns", component_id, "GitHub Actions Vulnerability Detection") :-
check_passed(component_id, "mcn_githubactions_vulnerabilities_1").
Copy link
Member

Choose a reason for hiding this comment

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

Please consistently use 4 spaces for indentation. This applies to all of the policy templates.

@Demolus13 Demolus13 force-pushed the pgovale/example-policies branch from 5381e89 to 8ab86ef Compare November 12, 2025 12:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

OCA Verified All contributors have signed the Oracle Contributor Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants