Skip to content

Embed independently reviewed threat-detect digests in compiled workflows #61855

Description

@davidslater

Summary

Finish the gh-aw side of independently pinned threat-detect installation.

The original trust-root gap is described in:

The detector repository completed the release-side prerequisite in:

That PR validates that every detector release publishes a complete, unambiguous
checksums.txt whose entries match the actual release binaries. It intentionally
does not change gh-aw, provide an installer for compiled workflows, or make a
runtime-downloaded checksum an independent trust root.

Current gap

gh-aw pins DefaultThreatDetectVersion, but
actions/setup/sh/install_threat_detect_binary.sh downloads both the selected
binary and checksums.txt from the same release URL. This detects accidental
corruption but does not independently authenticate the binary.

The release manifest is an input to review and pinning; it must not remain the
runtime trust root.

Implementation direction

Implement the following in github/gh-aw:

  1. Update DefaultThreatDetectVersion to v0.5.2 and define the reviewed
    release SHA-256 table next to it. Keep the complete detector release matrix
    as one review unit even though gh-aw currently executes only on Linux:

    Asset SHA-256
    threat-detect-linux-amd64 b4ecda6a8f1ee09913c40b58e5e9d3337d2173618d41b1bfdef9207e4e7959b9
    threat-detect-linux-arm64 f6260a0f9ad72bcb67c7af19c4ce262ca34e2c3d5ccbf912832a8bd277200904
    threat-detect-darwin-x64 7ed0a68ffbdd927eb2e25f862864602af289ad9cfc85f1385d83d4d52f11251c
    threat-detect-darwin-arm64 0d4f41134a0839a496ca34f5fbbce44ba89ca0be6d681f960e7c06070b8b04c6

    These values come from the promoted
    v0.5.2
    release produced after detector PR add-labels target not supported #1099 merged. Treat the version and digest
    table as one review unit whenever the detector pin is updated.

  2. Update buildInstallThreatDetectStep in
    pkg/workflow/threat_detection_steps.go so compiled *.lock.yml workflows
    contain the explicit release tag and digest pins. Because runner architecture
    is selected at runtime, emit both supported Linux pins or an equivalent
    complete mapping rather than guessing architecture at compile time.

  3. Add an optional, schema-validated artifact mirror base URL to gh-aw's
    workflow configuration, following the repository's existing naming and
    parsing conventions. The default remains the pinned GitHub Release URL. The
    compiler must carry the configured URL into the generated install step. Only
    the source of the bytes changes: the release tag and expected digest remain
    compiler-controlled and authoritative. Reject non-HTTPS mirror URLs.

  4. Update actions/setup/sh/install_threat_detect_binary.sh to:

    • require the independently supplied expected digest for the selected asset;
    • validate that the selected pin is exactly 64 lowercase hexadecimal
      characters;
    • download the binary for the pinned tag;
    • calculate its SHA-256 and compare it directly with the compiler-supplied
      pin before installing or executing it;
    • stop downloading or trusting checksums.txt at runtime;
    • fail without falling back to an unverified binary already on PATH or at
      the install destination.
  5. Preserve the existing strict/warn detection-failure policy. A failed download
    or verification must never produce a synthetic safe verdict or execute an
    unverified detector. In warn mode it may flow through the existing tolerated
    agent_failure handling; in strict mode it must fail the job.

  6. Update the detector-pin maintenance documentation so a version bump requires:

    • reviewing the promoted detector release;
    • copying the corresponding release digests into the trusted compiler
      constants;
    • updating version and digests in the same PR;
    • recompiling affected workflow fixtures/locks.

Do not copy or invoke gh-aw-threat-detection's
scripts/validate-release-checksums.sh from generated workflows. That script is
only a release-publication check in the detector repository. Generated workflows
need only the reviewed tag and digest values embedded by gh-aw.

gh-aw currently supports only Linux runners for agentic workflows, so this
issue should not add Darwin execution support. Preinstalled-binary support from
#57792 may be handled separately.

Acceptance criteria

  • A newly compiled lock contains the pinned detector tag and the complete Linux
    asset-to-digest mapping.
  • Installation no longer downloads checksums.txt.
  • Linux amd64 and arm64 select and verify the correct compiler-supplied digest.
  • The default source remains the pinned GitHub Release, while an approved HTTPS
    mirror can supply the same asset without changing or bypassing the expected
    digest.
  • Missing, malformed, duplicate/ambiguous, or mismatched pins fail before
    installation and detector execution.
  • A failed verification cannot fall back to a preexisting unverified
    threat-detect binary.
  • Installer tests cover both supported architectures, the default source, an
    HTTPS mirror, rejection of unsafe mirror URLs, a valid download, tampered
    bytes, missing/malformed pins, and the no-runtime-checksum behavior.
  • Compiler tests assert the version and digest literals emitted into generated
    YAML and prevent updating the version without a complete pin table.
  • Relevant generated fixtures/locks, documentation, and release notes/changeset
    are updated using the repository's normal process.

Intended trust flow

validated detector release
  -> human-reviewed version + digests in gh-aw source
  -> compiler embeds pins in *.lock.yml
  -> installer downloads selected binary
  -> installer verifies against embedded digest
  -> verified detector executes

This issue completes the consumer-side integration that detector PR #1099 was
designed to enable.

Activity

  1. wtgodbe commented on Sep 21, 2026

    @wtgodbe

    We are hitting this downstream in dotnet/aspnetcore's scheduled test-quarantine workflow:

    Both runs completed the main agent successfully, then failed the threat-detection gate with THREAT_DETECTION_STATUS: reason=invalid_report_exhausted exit=2 because no usable verdict reached the detector-owned result sink. In the earlier run, the detection model explicitly concluded ALLOW but no expected result file was produced; in the later run, the model refused the detection role and emitted no verdict. With retries=0, safe outputs were skipped and the generated quarantine PRs were not published.

    I also updated our local compiler to gh-aw v0.89.17 and regenerated all six agentic workflows from current dotnet/aspnetcore main. The generated locks still invoke:

    bash "${RUNNER_TEMP}/gh-aw/actions/install_threat_detect_binary.sh" v0.5.1

    So current gh-aw releases do not yet consume the v0.5.2 result-sink fix from github/gh-aw-threat-detection#1105 / github/gh-aw-threat-detection#1014. This provides a concrete downstream case for landing the version/digest update in #61857.

  2. locked and limited conversation to collaborators on Sep 21, 2026
  3. unlocked this conversation on Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions