Skip to content

[Safe Outputs Conformance] SEC-005: Cross-repo target-repo handlers need allowlist verification (work-queue Claim adapters) #67128

Description

@github-actions

Conformance Check Failure

Check ID: SEC-005
Severity: HIGH
Category: Security

Problem Description

scripts/check-safe-outputs-conformance.sh flagged 14 files under actions/setup/js/ for supporting a target-repo/targetRepo/target_repo field without a matching allowlist check (allowed.*[Rr]epos|validateTargetRepo|checkAllowedRepo). The safe-outputs specification (Section on Cross-Repository Validation, docs/src/content/docs/specs/safe-outputs-specification.md around line 648) states: "All handlers with target-repo parameter validate against allowlists; operations to non-allowlisted repos are rejected with E004."

Investigation shows all 14 matches come from the internal work-queue "Claim adapter" subsystem (not the user-facing cross-repo safe outputs like create_issue's resolveTargetRepoConfig/allowedRepos, which already pass this check). Two distinct root causes were found:

  1. Checker false-positive on test fixtures — 5 of the 14 files are self-contained Node test scripts (using node:assert/strict) that just happen to be named *_checks.cjs instead of *_test.cjs / *.test.cjs, so the script's test-file exclusion ([[ "$handler" =~ test ]]) misses them:

    • actions/setup/js/work_queue_claim_adapter_checks.cjs
    • actions/setup/js/work_queue_delivery_proof_checks.cjs
    • actions/setup/js/work_queue_git_tree_adapter_checks.cjs
    • actions/setup/js/work_queue_graphql_adapter_checks.cjs
    • actions/setup/js/work_queue_script_preparation_checks.cjs
  2. Genuinely production code using a different authorization mechanism — the remaining 9 files read adapter["target-repo"] after it has already been validated once, upstream, in actions/setup/js/work_queue_claim_adapters.cjs (closed() + a regex check at line 119: "Trusted Claim adapter requires a fixed repository scope"), and every write is additionally gated at effect-time by assertClaimAuthorized() (actions/setup/js/work_queue_claim_scope.cjs:180), which requires a per-Claim authorization proof:

    • actions/setup/js/finish_work_queue_claim.cjs:111
    • actions/setup/js/work_queue_claim_adapters.cjs:115,119,142
    • actions/setup/js/work_queue_code_scanning.cjs:32
    • actions/setup/js/work_queue_delivery.cjs:399
    • actions/setup/js/work_queue_git_tree_adapter.cjs:128
    • actions/setup/js/work_queue_graphql_adapter.cjs:114,118,119
    • actions/setup/js/work_queue_prepare_claim_adapter.cjs:30,36
    • actions/setup/js/work_queue_rest_adapter.cjs:94,95,97
    • actions/setup/js/work_queue_upload_assets.cjs:34

It is not yet confirmed whether this fixed-scope-regex + per-Claim-proof mechanism is an equivalent (or stronger) substitute for the "allowlist" the spec describes, or whether it is a genuine gap — e.g. if adapter["target-repo"] can ever be populated from multiple possible values rather than one build-time-fixed string, the spec's allowlist/E004-rejection requirement would not be satisfied.

Affected Components

  • Files: see checklist below
  • Script: scripts/check-safe-outputs-conformance.sh (check_cross_repo, SEC-005, lines 173-198)
  • Spec: docs/src/content/docs/specs/safe-outputs-specification.md (Cross-Repository Validation, ~line 648, ~line 665)
🔍 Current vs Expected Behavior

Current Behavior

  • The checker's test-file skip ([[ "$handler" =~ test ]]) does not match the *_checks.cjs naming convention used by several Node test scripts in this directory, so they are scanned as if they were production handlers.
  • Production work-queue Claim adapter files consume a target-repo value without any helper matching allowed.*[Rr]epos|validateTargetRepo|checkAllowedRepo, so the checker cannot confirm an allowlist exists, even though a single-fixed-repo regex check and a separate proof-based authorization call (assertClaimAuthorized) are present.

Expected Behavior

  • Test-only .cjs files should be excluded from SEC-005 scanning (either by broadening the script's skip pattern, or by renaming/annotating these fixtures).
  • Production handlers with a target-repo parameter should either demonstrably enforce an allowlist consistent with Section 9.4 of the spec (rejecting non-allowlisted repos with E004), or carry a documented @safe-outputs-exempt SEC-005 annotation explaining why the existing fixed-scope + per-Claim-authorization mechanism already satisfies that intent.

Remediation Steps

This task can be assigned to a Copilot coding agent with the following steps:

  1. Fix scripts/check-safe-outputs-conformance.sh's test-file exclusion in check_cross_repo (and ideally the other check functions sharing the same pattern) to also match _checks.cjs-style test fixtures, so files like work_queue_claim_adapter_checks.cjs are not scanned as production handlers.
  2. For each of the 9 genuine production files listed above, determine whether adapter["target-repo"] can ever resolve to more than one build-time-fixed value per adapter instance:
    • actions/setup/js/finish_work_queue_claim.cjs
    • actions/setup/js/work_queue_claim_adapters.cjs
    • actions/setup/js/work_queue_code_scanning.cjs
    • actions/setup/js/work_queue_delivery.cjs
    • actions/setup/js/work_queue_git_tree_adapter.cjs
    • actions/setup/js/work_queue_graphql_adapter.cjs
    • actions/setup/js/work_queue_prepare_claim_adapter.cjs
    • actions/setup/js/work_queue_rest_adapter.cjs
    • actions/setup/js/work_queue_upload_assets.cjs
  3. If the value is always a single build-time-fixed, regex-validated string (i.e. functionally an allowlist of one, already enforced in work_queue_claim_adapters.cjs), add a @safe-outputs-exempt SEC-005 annotation to each file with a one-line justification referencing work_queue_claim_adapters.cjs:119 and assertClaimAuthorized.
  4. If any handler can resolve target-repo from more than one possible value at runtime without going through that fixed-scope validation, add an explicit allowlist check (matching the spec's E004 rejection behavior) for that handler instead of an exemption.

Verification

After remediation, verify the fix by running:

bash scripts/check-safe-outputs-conformance.sh

The check SEC-005 should pass without errors (either via legitimate allowlist enforcement or documented, justified exemptions).

References

  • Safe Outputs Specification: docs/src/content/docs/specs/safe-outputs-specification.md
  • Conformance Checker: scripts/check-safe-outputs-conformance.sh
  • Run ID: 37890341772
  • Date: 2026-10-09

Generated by ✅ Daily Safe Outputs Conformance Checker · claude · agent · 107.7 AIC · ⊞ 5.2K · ◷

  • expires on Oct 9, 2026, 9:55 PM UTC-08:00

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions