diff --git a/.github/workflows/hide-codex-limit-comments.yml b/.github/workflows/hide-codex-limit-comments.yml index ed525b7..2bbd050 100644 --- a/.github/workflows/hide-codex-limit-comments.yml +++ b/.github/workflows/hide-codex-limit-comments.yml @@ -23,7 +23,7 @@ jobs: pull-requests: write steps: - name: Minimize comment - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 with: script: | const mutation = ` diff --git a/.github/workflows/monthly_snapshot_audit.yml b/.github/workflows/monthly_snapshot_audit.yml index 2317dc0..e623435 100644 --- a/.github/workflows/monthly_snapshot_audit.yml +++ b/.github/workflows/monthly_snapshot_audit.yml @@ -31,11 +31,11 @@ jobs: steps: - name: Checkout if: env.MONTHLY_SNAPSHOT_AUDIT_ENABLED != 'false' - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - name: Set Up Python if: env.MONTHLY_SNAPSHOT_AUDIT_ENABLED != 'false' - uses: actions/setup-python@v6 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 with: python-version: "3.11" @@ -72,7 +72,7 @@ jobs: - name: Upload Monthly Snapshot Audit Artifact if: env.MONTHLY_SNAPSHOT_AUDIT_ENABLED != 'false' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: ${{ steps.monthly_audit.outputs.artifact_name }} path: data/output/monthly_snapshot_audit @@ -168,7 +168,7 @@ jobs: id: codex_review_app_token if: steps.codex_review_app_credentials.outputs.available == 'true' continue-on-error: true - uses: actions/create-github-app-token@v3 + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 with: app-id: ${{ vars.CROSS_REPO_GITHUB_APP_ID }} private-key: ${{ secrets.CROSS_REPO_GITHUB_APP_PRIVATE_KEY }} diff --git a/tests/test_monthly_snapshot_audit_workflow.py b/tests/test_monthly_snapshot_audit_workflow.py index c8e3fc9..6c97e64 100644 --- a/tests/test_monthly_snapshot_audit_workflow.py +++ b/tests/test_monthly_snapshot_audit_workflow.py @@ -13,10 +13,10 @@ def test_monthly_snapshot_audit_workflow_dispatches_codex_bridge(): assert "actions: write" in workflow assert "contents: read" in workflow assert "issues: write" in workflow - assert "actions/checkout@v6" in workflow - assert "actions/setup-python@v6" in workflow - assert "actions/upload-artifact@v7" in workflow - assert "actions/create-github-app-token@v3" in workflow + assert "actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6" in workflow + assert "actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6" in workflow + assert "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7" in workflow + assert "actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3" in workflow assert "write_monthly_snapshot_audit_issue.py" in workflow assert "monthly_snapshot_audit_issue.json" in workflow assert "QuantStrategyLab/AIAuditBridge" in workflow diff --git a/tests/test_privileged_workflow_action_pins.py b/tests/test_privileged_workflow_action_pins.py new file mode 100644 index 0000000..583884e --- /dev/null +++ b/tests/test_privileged_workflow_action_pins.py @@ -0,0 +1,18 @@ +from pathlib import Path +import re + + +WORKFLOWS = ( + Path(".github/workflows/monthly_snapshot_audit.yml"), + Path(".github/workflows/hide-codex-limit-comments.yml"), +) +FULL_SHA_ACTION = re.compile(r"uses:\s+[^\s@]+@[0-9a-f]{40}(?:\s+#\s+v\d+)?$") + + +def test_privileged_workflows_pin_remote_actions_to_full_commit_shas(): + for path in WORKFLOWS: + workflow = path.read_text(encoding="utf-8") + action_lines = [line.strip() for line in workflow.splitlines() if "uses:" in line] + + assert action_lines + assert all(FULL_SHA_ACTION.fullmatch(line) for line in action_lines)