diff --git a/.github/workflows/test_macaron_action.yaml b/.github/workflows/test_macaron_action.yaml
index 5f3753a98..2621313c6 100644
--- a/.github/workflows/test_macaron_action.yaml
+++ b/.github/workflows/test_macaron_action.yaml
@@ -184,7 +184,7 @@ jobs:
package_url: pkg:maven/io.github.behnazh-w.demo/example-maven-app@2.0?type=jar
repo_path: https://github.com/behnazh-w/example-maven-app
output_dir: macaron_output/detect_malicious_java_dep
- sbom_path: ./resources/detect_malicious_java_dep/example-sbom.json
+ sbom_path: ./tests/tutorial_resources/detect_malicious_java_dep/example-sbom.json
deps_depth: '1'
- name: Run Macaron (verify policy - detect-malicious-upload)
diff --git a/README.md b/README.md
index d77aca1d5..b4054181f 100644
--- a/README.md
+++ b/README.md
@@ -4,11 +4,26 @@

-[Full Documentation](https://oracle.github.io/macaron/index.html) | [Tutorials](https://oracle.github.io/macaron/pages/tutorials/index.html) | [Videos](https://www.youtube.com/watch?v=ebo0kGKP6bw) | [Papers](#publications) | [Presentations](#presentations)
+[Full Documentation](https://oracle.github.io/macaron/index.html) | [Tutorials](https://oracle.github.io/macaron/pages/tutorials/index.html) | [Videos](https://www.youtube.com/watch?v=ebo0kGKP6bw) | [Papers](#publications) | [Presentations](#presentations) | [Macaron GitHub Action](https://oracle.github.io/macaron/pages/macaron_action.html)
**Macaron** is a software supply chain security analysis tool from Oracle Labs focused on verifying the **build integrity** of artifacts and their dependencies. It helps developers, security teams, and researchers ensure that packages are built as expected and have not been tampered with.
+Use Macaron as a GitHub Action
+
+To use the Macaron GitHub Action, add the following step to your workflow:
+```yaml
+- uses: oracle/macaron@v0.21.0
+ with:
+ repo_path: 'https://github.com/example/project'
+ policy_file: check-github-actions
+ policy_purl: 'pkg:github.com/example/project'
+ output_dir: 'macaron-output'
+ upload_attestation: true
+```
+
+For detailed instructions and a comprehensive list of available options, please refer to the [Macaron GitHub Action documentation](https://oracle.github.io/macaron/pages/macaron_action.html).
+
## Key Capabilities
Macaron supports:
diff --git a/action.yaml b/action.yaml
index 0e77b216d..9cd282cf0 100644
--- a/action.yaml
+++ b/action.yaml
@@ -58,25 +58,8 @@ outputs:
runs:
using: composite
steps:
- - name: Setup Python
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
- with:
- python-version: 3.11.14
-
- - name: Setup Go
- uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
- with:
- go-version: '1.23'
- cache: false
-
- - name: Setup JDK
- uses: actions/setup-java@b36c23c0d998641eff861008f374ee103c25ac73 # v4.4.0
- with:
- java-version: '17'
- distribution: oracle
-
- name: Setup Macaron
- # Create or reuse a Python virtualenv with the macaron CLI and export the `MACARON` binary path via `$GITHUB_ENV` so later steps can use it.
+ # Create or reuse run_macaron.sh script
run: |
bash "$GITHUB_ACTION_PATH/scripts/actions/setup_macaron.sh"
shell: bash
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 43fe2af7f..bc9ab5a0d 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -121,6 +121,7 @@ intermediate representations as abstractions. Using such abstractions, Macaron i
pages/installation
pages/using
pages/cli_usage/index
+ pages/macaron_action
pages/tutorials/index
pages/output_files
pages/checks/slsa_builds
diff --git a/docs/source/pages/macaron_action.rst b/docs/source/pages/macaron_action.rst
new file mode 100644
index 000000000..450e40870
--- /dev/null
+++ b/docs/source/pages/macaron_action.rst
@@ -0,0 +1,134 @@
+Macaron GitHub Action
+=====================
+
+Overview
+--------
+
+This document describes the composite GitHub Action defined in ``action.yaml`` at the repository root. The action uses the Macaron CLI to run supply-chain security analysis and policy verification from a GitHub Actions workflow.
+
+Quick usage
+-----------
+
+When using this action you can reference the action in your workflow. Example:
+
+.. code-block:: yaml
+
+ jobs:
+ analyze:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ - name: Run Macaron Security Analysis
+ uses: oracle/macaron@v0.21.0
+ with:
+ repo_path: 'https://github.com/example/project'
+ policy_file: check-github-actions
+ policy_purl: 'pkg:github.com/example/project'
+ output_dir: 'macaron-output'
+ upload_attestation: true
+
+Example: policy verification only
+----------------------------------
+
+To run only the policy verification step (when you already have an output
+database), call the action with ``policy_file`` and set ``output_dir`` to the
+directory containing ``macaron.db``:
+
+.. code-block:: yaml
+
+ - name: Verify policy
+ uses: oracle/macaron@v0.21.0
+ with:
+ policy_file: policy.dl
+ output_dir: macaron-output
+ upload_attestation: true
+
+Inputs
+------
+The action exposes a number of inputs which map directly to Macaron CLI
+options. Key inputs are listed below (see ``action.yaml`` for the full list):
+
+.. list-table:: Action inputs
+ :header-rows: 1
+ :widths: 20 60 20
+
+ * - Input
+ - Description
+ - Default
+ * - ``repo_path``
+ - The path or URL of the repository to analyze.
+ -
+ * - ``package_url``
+ - A PURL identifying a package to analyze instead of a repository.
+ -
+ * - ``sbom_path``
+ - Path to an SBOM file to analyze.
+ -
+ * - ``python_venv``
+ - Path to an existing Python virtualenv (used when analyzing Python
+ packages).
+ -
+ * - ``defaults_path``
+ - Path to a Macaron defaults configuration file.
+ -
+ * - ``policy_file``
+ - Path to a Datalog policy file for policy verification.
+ -
+ * - ``policy_purl``
+ - PURL for a pre-defined policy to use with verification.
+ -
+ * - ``branch`` / ``digest``
+ - Checkout options when analyzing a repository (branch name or commit
+ digest).
+ -
+ * - ``deps_depth``
+ - Dependency resolution depth (how many levels of transitive dependencies
+ to resolve).
+ - ``0``
+ * - ``github_token``
+ - Token used by Macaron to access GitHub (for cloning, API access,
+ etc.).
+ - ``${{ github.token }}``
+ * - ``output_dir``
+ - Directory where Macaron writes results (database, reports, artifacts).
+ - ``output``
+ * - ``upload_attestation``
+ - When ``true``, the action will attempt to upload a generated
+ verification attestation (VSA) after policy verification.
+ - ``false``
+
+Outputs
+-------
+
+The composite action exposes the following outputs (set by the
+``run_macaron_policy_verification.sh`` script when applicable):
+
+.. list-table:: Action outputs
+ :header-rows: 1
+ :widths: 20 70
+
+ * - Output
+ - Description
+ * - ``policy_report``
+ - Path to the generated policy report JSON file produced by
+ ``macaron verify-policy``. This file contains the policy evaluation
+ results.
+ * - ``vsa_report``
+ - Path to the generated VSA (Verification Summary Attestation) in
+ `in-toto `_ JSONL format. If no VSA was produced
+ during verification, the action emits the string ``"VSA Not Generated."``
+ instead of a path.
+
+How the action works
+--------------------
+
+1. ``Setup Macaron``: downloads ``run_macaron.sh`` script to install and run macaron in the action.
+
+2. ``Run Macaron Analysis``: calls ``scripts/actions/run_macaron_analysis.sh``
+ which assembles the ``macaron analyze`` command from the inputs and runs
+ it. Results are written into ``output_dir``.
+
+3. ``Run Macaron Policy Verification``: if a policy file or PURL is supplied,
+ the corresponding script runs ``macaron verify-policy`` against the
+ analysis database and writes ``policy_report`` and ``vsa_report`` to
+ ``$GITHUB_OUTPUT`` when produced.
diff --git a/scripts/actions/run_macaron_analysis.sh b/scripts/actions/run_macaron_analysis.sh
index fc97fd916..34305479c 100644
--- a/scripts/actions/run_macaron_analysis.sh
+++ b/scripts/actions/run_macaron_analysis.sh
@@ -19,7 +19,7 @@ else
fi
OUTPUT_DIR=${OUTPUT_DIR:-output}
-CMD="$CMD --output-dir ${OUTPUT_DIR} -lr . analyze"
+CMD="$CMD --output ${OUTPUT_DIR} -lr . analyze"
if [ -n "${REPO_PATH:-}" ]; then
CMD="$CMD -rp ${REPO_PATH}"
diff --git a/scripts/actions/run_macaron_policy_verification.sh b/scripts/actions/run_macaron_policy_verification.sh
index fb6218e36..46eb9bee0 100644
--- a/scripts/actions/run_macaron_policy_verification.sh
+++ b/scripts/actions/run_macaron_policy_verification.sh
@@ -25,7 +25,7 @@ if [ -n "$DEFAULTS_PATH" ]; then
else
CMD="$MACARON"
fi
-CMD="$CMD --output-dir ${OUTPUT_DIR} verify-policy --database ${OUTPUT_DIR}/macaron.db"
+CMD="$CMD --output ${OUTPUT_DIR} verify-policy --database ${OUTPUT_DIR}/macaron.db"
if [ -n "$FILE" ] && [ -f "$FILE" ]; then
CMD="$CMD --file $FILE"
diff --git a/scripts/actions/setup_macaron.sh b/scripts/actions/setup_macaron.sh
index fe2bd9b20..978aab93e 100644
--- a/scripts/actions/setup_macaron.sh
+++ b/scripts/actions/setup_macaron.sh
@@ -4,25 +4,59 @@
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/.
set -euo pipefail
-# Setup Macaron virtualenv and make available via GitHub Actions environment files.
-# This script writes `MACARON=` to `$GITHUB_ENV` so later steps can invoke the macaron CLI, and appends the venv `bin` directory to `$GITHUB_PATH`.
-
MACARON_DIR="${RUNNER_TEMP:-/tmp}/macaron"
-VENV_MACARON="$MACARON_DIR/.venv/bin/macaron"
-
mkdir -p "$MACARON_DIR"
-if [ -x "$VENV_MACARON" ]; then
- echo "Using macaron from existing venv: $VENV_MACARON"
- echo "MACARON=$VENV_MACARON" >> "$GITHUB_ENV"
- echo "$MACARON_DIR/.venv/bin" >> "$GITHUB_PATH"
- exit 0
+ref="$GITHUB_REF"
+MACARON_IMAGE_TAG=""
+cd "$GITHUB_ACTION_PATH"
+if [[ "$ref" == refs/tags/* ]]; then
+ MACARON_IMAGE_TAG="${ref#refs/tags/}"
+ echo "Ref is a tag: $MACARON_IMAGE_TAG"
+else
+ sha="$GITHUB_SHA"
+ if [[ -z "$sha" ]]; then
+ sha="$ref"
+ fi
+ # Check for tags pointing directly at the SHA.
+ tags=$(git tag --points-at "$sha")
+ if [[ -n "$tags" ]]; then
+ # Get the first tag (main or first one listed)
+ MACARON_IMAGE_TAG="$(echo "$tags" | head -n1)"
+ echo "Commit $sha matches tag: $MACARON_IMAGE_TAG"
+ else
+ # Search all tags that contain the commit (could be ancestor).
+ history_tags=$(git tag --contains "$sha")
+ if [[ -n "$history_tags" ]]; then
+ MACARON_IMAGE_TAG="$(echo "$history_tags" | head -n1)"
+ echo "Commit $sha is contained by tag: $MACARON_IMAGE_TAG"
+ else
+ echo "No tags found for commit $sha"
+ fi
+ fi
fi
cd "$MACARON_DIR"
-git clone https://github.com/oracle/macaron.git .
-make venv
-export PATH="$MACARON_DIR/.venv/bin:$PATH"
-make setup
-echo "MACARON=$VENV_MACARON" >> "$GITHUB_ENV"
-echo "$MACARON_DIR/.venv/bin" >> "$GITHUB_PATH"
+
+# Download image using macaron_image_tag else latest release
+if [ "${MACARON_IMAGE_TAG}" != "" ]; then
+ echo "MACARON_IMAGE_TAG detected: ${MACARON_IMAGE_TAG}"
+ URL="https://raw.githubusercontent.com/oracle/macaron/refs/tags/${MACARON_IMAGE_TAG}/scripts/release_scripts/run_macaron.sh"
+ SCRIPT_NAME="run_macaron_${MACARON_IMAGE_TAG}.sh"
+else
+ echo "Using default latest release."
+ URL="https://raw.githubusercontent.com/oracle/macaron/release/scripts/release_scripts/run_macaron.sh"
+ SCRIPT_NAME="run_macaron.sh"
+fi
+
+# Get the run_macaron.sh script
+if [ ! -f "$SCRIPT_NAME" ]; then
+ echo "Downloading $SCRIPT_NAME from: $URL"
+ curl -fSL -o "$SCRIPT_NAME" "$URL"
+else
+ echo "$SCRIPT_NAME already exists, skipping download."
+fi
+
+chmod +x "$SCRIPT_NAME"
+echo "MACARON=$MACARON_DIR/$SCRIPT_NAME" >> "$GITHUB_ENV"
+echo "MACARON_IMAGE_TAG=${MACARON_IMAGE_TAG}" >> "$GITHUB_ENV"
diff --git a/src/macaron/resources/policies/datalog/malware-detection.dl.template b/src/macaron/resources/policies/datalog/malware-detection.dl.template
index 77eedc5cf..4429cfec6 100644
--- a/src/macaron/resources/policies/datalog/malware-detection.dl.template
+++ b/src/macaron/resources/policies/datalog/malware-detection.dl.template
@@ -3,7 +3,6 @@
Policy("check-component", component_id, "Check component artifacts.") :-
check_passed(component_id, "mcn_detect_malicious_metadata_1").
-
apply_policy_to("check-component", component_id) :-
is_component(component_id, purl),
match("", purl).