Skip to content

Tracking: parity with gh-aw's inline threat detection before migrating workflows to the external detector #705

Description

@davidslater

Created by GitHub Ace · View Session

Context

gh-aw still runs the inline threat-detection path in most compiled workflows: the detection job executes the agentic engine directly under AWF, scrapes THREAT_DETECTION_RESULT: out of detection.log with parse_threat_detection_results.cjs, and concludes with core.setOutput/core.setFailed. The external path (features: gh-aw-detection: true) downloads this repo's threat-detect binary and concludes via conclude_threat_detection.shthreat-detect conclude.

Most recent relevant change upstream: github/gh-aw#48940 — engine failures (agent_failure, parse_error) now render as [!WARNING] threat detection engine error instead of [!CAUTION] agentic threat detected, keyed off isToolingFailureReason(reason). That makes the reason output load-bearing for user-facing severity, which raises the bar for our conclusion contract.

We made genuinely useful improvements when we diverged (out-of-band result sink instead of log scraping, trusted-vs-untrusted prompt analysis, structured JSONL run log, self-correction retries, an explicit terminal status line). This issue tracks everything that would regress if gh-aw flipped its workflows to this repo today.

Audit scope

Reviewed against gh-aw @ main:

  • pkg/workflow/threat_detection_{job,steps,inline_engine,external,config,helpers}.go
  • actions/setup/js/{setup_threat_detection,parse_threat_detection_results,threat_detection_warning,messages_run_status,generate_footer}.cjs
  • actions/setup/sh/{install_threat_detect_binary,conclude_threat_detection}.sh
  • actions/setup/md/{threat_detection,threat_warning_request_changes_review}.md
  • docs/src/content/docs/reference/threat-detection.md, ADRs 29031 / 29257 / 28160 / 38166 / 41231

Findings

Blocking — features that are silently inert or fail-open today

# Issue Summary
1 #686 prompt-template.txt / prompt-import-tree.json are never staged into the detection dir → the trusted-vs-untrusted prompt analysis, our flagship improvement, is a no-op in production
2 #688 CUSTOM_PROMPT / WORKFLOW_NAME / WORKFLOW_DESCRIPTION never reach the detector → safe-outputs.threat-detection.prompt is silently ignored
3 #693 parse_error is unreachable — every THREAT_DETECTION_STATUS: reason collapses to agent_failure, discarding the granularity #48940 depends on
4 #694 Conclusion logic duplicated across conclude_threat_detection.sh and threat-detect conclude; strict-mode missing-file branch writes no reason, which renders an infra failure as [!CAUTION] agentic threat detected — the exact bug #48940 fixed. Also an undocumented fail-closed divergence from ADR 29031's warn-mode resilience
5 #701 Degraded/absent artifacts produce a clean verdict with no annotation — fail-open in a security control

Detection-coverage / accuracy regressions

# Issue Summary
6 #689 comment-memory files are not analyzed ({COMMENT_MEMORY_FILES} section dropped)
7 #691 npm lockfile false-positive suppression guidance dropped from the prompt
8 #704 aw_info.json (activation/trigger context) and experiments/ documented but never loaded

Observability regressions

# Issue Summary
9 #692 threat-detect conclude emits far less diagnostic output than parse_threat_detection_results.cjs (no verdict breakdown, no input echo, no directory listing, no log stats)
10 #696 Step summary renders gh-aw's unused prompt; the detector contributes neither the prompt it used nor a verdict summary
11 #697 The structured JSONL run log (--log-file) is never enabled or uploaded
12 #698 aic token-usage parsing unverified; max-ai-credits budget not enforced on the external path

Packaging

# Issue Summary
13 #695 No THREAT_DETECTION_RESULT: line emitted, so gh-aw's log-scraping fallback can never recover a verdict
14 #702 gh-aw's installer supports threat-detect-darwin-* assets we never publish

Suggested sequencing

  1. Parity: conclusion logic is duplicated in conclude_threat_detection.sh and threat-detect conclude, with divergent (and partly broken) semantics #694 + Parity: parse_error is unreachable on the external path — THREAT_DETECTION_STATUS reasons are collapsed to agent_failure #693 first — they define the conclusion contract everything else reports through, and Parity: conclusion logic is duplicated in conclude_threat_detection.sh and threat-detect conclude, with divergent (and partly broken) semantics #694 contains a live correctness bug.
  2. Parity: prompt-template.txt / prompt-import-tree.json are never staged, so trusted-vs-untrusted prompt analysis is silently disabled #686 + Parity: CUSTOM_PROMPT / WORKFLOW_NAME / WORKFLOW_DESCRIPTION never reach threat-detect, so threat-detection.prompt is silently ignored #688 + Parity: missing ERR_VALIDATION warnings — degraded/absent artifacts silently produce a clean verdict (fail-open) #701 — restore the inputs and make degradation loud. Without these the detector is running on far less context than the inline path.
  3. Parity: threat-detect emits no THREAT_DETECTION_RESULT: line, so gh-aw's detection-log fallback can never recover a verdict #695 — cheap resilience, no gh-aw change required.
  4. Parity: threat-detect conclude emits far less diagnostic output than parse_threat_detection_results.cjs #692 + Parity: step summary shows gh-aw's unused prompt; threat-detect contributes no prompt or verdict summary #696 + Parity: the structured JSONL run log (--log-file) is never enabled or uploaded on the external detector path #697 — observability, so the remaining items are diagnosable from a job log.
  5. Parity: comment-memory files are not analyzed (missing {COMMENT_MEMORY_FILES} prompt section and artifact discovery) #689 + Parity: npm lockfile false-positive suppression guidance dropped from the detection prompt #691 + Parity: AI-credit reporting (aic) unverified and max-ai-credits budget not enforced on the external detector path #698 + Parity: documented artifacts aw_info.json and experiments/ are never loaded or surfaced #704 + Parity: gh-aw's installer supports threat-detect-darwin-* assets that we never publish #702 — coverage, cost, and packaging.

Several items need a paired PR in github/gh-aw (staging step, execution-step env, external command flags, artifact upload paths). Those should be filed upstream and linked back here.

Definition of done

  • Every item above closed or explicitly waived with rationale recorded in specs/threat-detection-spec.md.
  • A side-by-side run of the same workflow on both paths produces equivalent job-log diagnostics, equivalent conclusion/reason/success outputs across the full failure matrix, and an equivalent (or better) verdict.
  • specs/threat-detection-spec.md and specs/usage-spec.md updated to describe the resulting contract normatively.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions