Skip to content
Open
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
41 changes: 41 additions & 0 deletions .github/workflows/test_macaron_action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -411,3 +411,44 @@ jobs:
echo "Expected verify step to fail, but it did not."
exit 1
fi

test-detect-composite-injection:
name: Detect injection in composite GitHub Actions
runs-on: ubuntu-latest
env:
MACARON_IMAGE_TAG: ${{ inputs.macaron_image_tag }}
DOCKER_PULL: never
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Download test Docker image artifact
if: ${{ inputs.docker_image_artifact_name != '' }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: ${{ inputs.docker_image_artifact_name }}
path: /tmp
- name: Load test Docker image
if: ${{ inputs.docker_image_artifact_name != '' }}
run: docker load --input /tmp/macaron-test-image.tar

- name: Run Macaron (analyze github_actions_vulns for https://github.com/oracle/macaron)
id: verify_github_actions_vulns_repo_test
# This integration target is intentionally vulnerable; failure is expected.
continue-on-error: true
uses: ./
with:
repo_path: https://github.com/oracle/macaron
digest: 59bfc67471b8c95afc816faf71760a51efff91a5
policy_file: check-github-actions
policy_purl: pkg:github.com/oracle/macaron@.*
output_dir: macaron_output/detect_vulnerable_github_actions
upload_reports: 'false'
reports_artifact_name: macaron-injection-actions-fail-diagnosis
write_job_summary: 'true'
- name: Assert expected failure (github_actions_vulns for repo test)
if: ${{ always() }}
run: |
# Explicitly assert failure so regressions are visible in CI results.
if [ "${{ steps.verify_github_actions_vulns_repo_test.outcome }}" != "failure" ]; then
echo "Expected verify step to fail, but it did not."
exit 1
fi
37 changes: 35 additions & 2 deletions src/macaron/code_analyzer/dataflow_analysis/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@

from __future__ import annotations

import os
from collections.abc import Iterable
from typing import cast

from macaron.code_analyzer.dataflow_analysis import bash, core, evaluation, facts, github, printing
from macaron.errors import CallGraphError
Expand Down Expand Up @@ -51,7 +53,11 @@ def analyse_github_workflow_file(workflow_path: str, repo_path: str | None, dump


def analyse_github_workflow(
workflow: github_workflow_model.Workflow, workflow_source_path: str, repo_path: str | None, dump_debug: bool = False
workflow: github_workflow_model.Workflow,
workflow_source_path: str,
repo_path: str | None,
dump_debug: bool = False,
local_action_stack: tuple[str, ...] = (),
) -> core.Node:
"""Perform dataflow analysis for GitHub Actions Workflow.

Expand All @@ -75,7 +81,9 @@ def analyse_github_workflow(
analysis_context = core.OwningContextRef(core.AnalysisContext(repo_path))

core.reset_debug_sequence_number()
raw_workflow_node = github.RawGitHubActionsWorkflowNode.create(workflow, analysis_context, workflow_source_path)
raw_workflow_node = github.RawGitHubActionsWorkflowNode.create(
workflow, analysis_context, workflow_source_path, local_action_stack
)
core.increment_debug_sequence_number()

raw_workflow_node.analyse()
Expand All @@ -89,6 +97,31 @@ def analyse_github_workflow(
return raw_workflow_node


def analyse_github_composite_action_file(
action_path: str, repo_path: str | None, dump_debug: bool = False
) -> core.Node:
"""Perform dataflow analysis for a standalone local composite GitHub Action metadata file.

The action is wrapped in a synthetic workflow so existing GitHub Actions analyses can traverse
its nested ``run`` and ``uses`` steps without a separate root node type.
"""
steps = github.parse_composite_action_steps(action_path)
workflow = cast(
github_workflow_model.Workflow,
{
"name": action_path,
"on": "workflow_call",
"jobs": {
"composite-action": {
"runs-on": "ubuntu-latest",
"steps": steps,
}
},
},
)
return analyse_github_workflow(workflow, action_path, repo_path, dump_debug, (os.path.abspath(action_path),))


def analyse_bash_script(
bash_content: str, source_path: str, repo_path: str | None, dump_debug: bool = False
) -> core.Node:
Expand Down
Loading
Loading