From 3d112b0e4eeba5f5576ded962258a539c3cdfab5 Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Thu, 28 May 2026 01:52:00 +0200 Subject: [PATCH] gateway: emit with.version for known unpinned-tools actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `1Password/load-secrets-action` with an inline `# zizmor: ignore[]` comment, but placed it on the `if: false` line. zizmor only honours the ignore on the line where the finding lives — line 40 (the `- uses:` line) — so the suppression never took effect, and #885 (zizmor 0.5.5 → 0.5.6 bump) has been stuck failing CI ever since. Inline placement on the `- uses:` line would also be fragile: it sits next to dependabot's `# v4.0.0` version comment, and dependabot rewrites that comment on every bump. The zizmor docs (configuration guide) also state that "composite action findings cannot be ignored via `zizmor.yml`", so the config-file path is closed. The audit's actual remediation (per its source at crates/zizmor/src/audit/unpinned_tools.rs) is to set a static `with.version` value. The audit fires only when the input is missing or literal `latest`. Setting it to any specific string silences the finding. Since these composite entries are `if: false` (allowlist registration only — they never execute), the version value is cosmetic; only the static analyser cares. This change: - Adds `_unpinned_tool_version_pin()` + `_UNPINNED_TOOLS_VERSION_PINS` in `gateway/gateway.py` so the composite generator emits a `with.version` block for any action zizmor's `unpinned-tools` audit knows about (currently `1password/load-secrets-action` and `aquasecurity/setup-trivy`; the latter is preemptive — we don't carry it on the allowlist today). - Applies the same `with.version` block manually to the existing `1Password/load-secrets-action` entries in the composite. The next full regeneration (post #892's pipeline recovery) will produce identical content; the manual edit only fast-paths the fix so #885 can land immediately. - Drops the no-op `# zizmor: ignore[unpinned-tools]` tail comment #886 added on the `if: false` line — the version pin is now the real suppression mechanism. Local verification: `zizmor --min-severity medium --min-confidence medium .github/ allowlist-check/ pelican/ stash/` now reports "No findings to report. Good job!" (down from 1 medium). Gateway tests still pass (8 passed). Generated-by: Claude Opus 4.7 --- .../action.yml | 4 +++ gateway/gateway.py | 28 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/.github/actions/for-dependabot-triggered-reviews/action.yml b/.github/actions/for-dependabot-triggered-reviews/action.yml index 1b493a97..e42677ac 100644 --- a/.github/actions/for-dependabot-triggered-reviews/action.yml +++ b/.github/actions/for-dependabot-triggered-reviews/action.yml @@ -39,8 +39,12 @@ runs: steps: - uses: 1Password/load-secrets-action@92467eb28f72e8255933372f1e0707c567ce2259 # v4.0.0 if: false + with: + version: "2.30.0" - uses: 1Password/load-secrets-action/configure@92467eb28f72e8255933372f1e0707c567ce2259 # v4.0.0 if: false + with: + version: "2.30.0" - uses: addnab/docker-run-action@4f65fabd2431ebc8d299f8e5a018d79a769ae185 # v3 if: false - uses: advanced-security/dismiss-alerts@046d6b48d2e43cf563f96f67332c47c432eff83e # v2.0.2 diff --git a/gateway/gateway.py b/gateway/gateway.py index 88ab59df..c0a068c7 100644 --- a/gateway/gateway.py +++ b/gateway/gateway.py @@ -201,10 +201,38 @@ def is_updatable(ref): details = refs[ref] steps.append(f" - uses: {name}@{ref}" + (f" # {details['tag']}" if details and 'tag' in details else '')) steps.append( " if: false") + # zizmor's `unpinned-tools` audit flags certain actions whose + # default behavior is to install the "latest" version of an + # external tool. The remediation is to set `with.version` to + # a specific value. These steps never execute (`if: false`); + # the value is cosmetic, only here so the static analyser is + # satisfied. See https://docs.zizmor.sh/audits/#unpinned-tools + pin = _unpinned_tool_version_pin(name) + if pin is not None: + steps.append(" with:") + steps.append(f' version: "{pin}"') return header + "\n".join(steps) + "\n" + " - run: echo Success!\n" + " shell: bash\n" +# zizmor's `unpinned-tools` audit (zizmor source: +# crates/zizmor/src/audit/unpinned_tools.rs) reports a Medium finding when one +# of these actions is used without a static `with.version`. Keys are matched +# case-insensitively against the bare repo name and any subpath under it. +_UNPINNED_TOOLS_VERSION_PINS = { + "1password/load-secrets-action": "2.30.0", + "aquasecurity/setup-trivy": "v0.55.0", +} + + +def _unpinned_tool_version_pin(name: str) -> str | None: + name_l = name.lower() + for prefix, version in _UNPINNED_TOOLS_VERSION_PINS.items(): + if name_l == prefix or name_l.startswith(prefix + "/"): + return version + return None + + def update_refs( composite_steps: list[dict[str, str]], action_refs: ActionsYAML ) -> ActionsYAML: