Skip to content

Commit b6ad524

Browse files
davidslaterGitHub Ace
andauthored
fix(cli): accept and ignore deprecated --step-summary flag (#804)
Older gh-aw releases still pass --step-summary to the detector, which aborted detection with "flag provided but not defined" since the step summary output was removed. Parse the flag, drop its value, and note on stderr that it was ignored. Co-authored-by: GitHub Ace <githubnext@users.noreply.github.com> Co-authored-by: David Slater <12449447+davidslater@users.noreply.github.com>
1 parent be974f2 commit b6ad524

5 files changed

Lines changed: 64 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ threat-detect [flags] <artifacts-dir>
6363
- `--custom-prompt-file` — Path to a file with additional detection instructions. Takes precedence over `--custom-prompt` and `CUSTOM_PROMPT`
6464
- `--output` — Path to write JSON result (defaults to stdout)
6565
- `--retries` — Retries for malformed detection outputs. Default: `1` (env: `THREAT_DETECTION_RETRIES`)
66+
- `--step-summary` — Deprecated and ignored. Accepted so hosts that still pass it (older `gh-aw` releases) do not fail; the detector no longer writes a GitHub Actions step summary
6667
- `--version` — Print version and exit
6768

6869
`threat-detect` runs a single agentic CLI engine pass. The engine reports its

cmd/threat-detect/main.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ func run() (code int) {
115115
workflowDescription string
116116
customPrompt string
117117
customPromptFile string
118+
stepSummary string
118119
version bool
119120
retries int
120121
)
@@ -132,6 +133,11 @@ func run() (code int) {
132133
flag.StringVar(&workflowDescription, "workflow-description", "", "Workflow description for the prompt (overrides WORKFLOW_DESCRIPTION)")
133134
flag.StringVar(&customPrompt, "custom-prompt", "", "Additional detection instructions appended to the prompt (overrides CUSTOM_PROMPT)")
134135
flag.StringVar(&customPromptFile, "custom-prompt-file", "", "Path to a file with additional detection instructions (takes precedence over --custom-prompt and CUSTOM_PROMPT)")
136+
// Accepted and ignored for backward compatibility: older gh-aw releases pass
137+
// --step-summary, but the detector no longer writes a step summary (TD-20c).
138+
// Rejecting the flag would abort detection in those hosts, so it is parsed
139+
// and dropped instead.
140+
flag.StringVar(&stepSummary, "step-summary", "", "Deprecated and ignored; the detector no longer writes a GitHub Actions step summary")
135141
flag.BoolVar(&version, "version", false, "Print version and exit")
136142
flag.IntVar(&retries, "retries", envInt("THREAT_DETECTION_RETRIES", 1), "Retries for malformed detection outputs (env: THREAT_DETECTION_RETRIES)")
137143
if err := flag.CommandLine.Parse(os.Args[1:]); err != nil {
@@ -148,6 +154,17 @@ func run() (code int) {
148154
return exitSafe
149155
}
150156

157+
stepSummaryProvided := false
158+
flag.CommandLine.Visit(func(f *flag.Flag) {
159+
if f.Name == "step-summary" {
160+
stepSummaryProvided = true
161+
}
162+
})
163+
if stepSummaryProvided {
164+
fmt.Fprintf(os.Stderr, "[threat-detect] ignoring deprecated --step-summary %s: the detector no longer writes a step summary\n",
165+
sanitizeLogValue(stepSummary))
166+
}
167+
151168
// When --model is not set, fall back to the engine-specific detection model
152169
// environment variable (GH_AW_MODEL_DETECTION_{COPILOT,CLAUDE,CODEX}) or the
153170
// engine CLI's native model env var (COPILOT_MODEL, ANTHROPIC_MODEL), so the

cmd/threat-detect/main_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,3 +827,44 @@ func TestRunStartLineEscapesEngineID(t *testing.T) {
827827
}
828828
}
829829
}
830+
831+
// TestRunAcceptsAndIgnoresStepSummaryFlag verifies the removed --step-summary
832+
// option is still parsed and dropped (TD-20c) so hosts that still pass it do not
833+
// abort detection with a flag error.
834+
func TestRunAcceptsAndIgnoresStepSummaryFlag(t *testing.T) {
835+
artifactsDir := t.TempDir()
836+
if err := os.MkdirAll(filepath.Join(artifactsDir, "aw-prompts"), 0o755); err != nil {
837+
t.Fatalf("MkdirAll error = %v", err)
838+
}
839+
if err := os.WriteFile(filepath.Join(artifactsDir, "aw-prompts", "prompt.txt"), []byte("analyze this"), 0o600); err != nil {
840+
t.Fatalf("WriteFile error = %v", err)
841+
}
842+
if err := os.WriteFile(filepath.Join(artifactsDir, "agent_output.json"), []byte(`{"items":[]}`), 0o600); err != nil {
843+
t.Fatalf("WriteFile error = %v", err)
844+
}
845+
846+
outputPath := filepath.Join(t.TempDir(), "result.json")
847+
summaryPath := filepath.Join(t.TempDir(), "step-summary.md")
848+
copilotMarker := filepath.Join(t.TempDir(), "copilot-called")
849+
sinkJSON := `{"prompt_injection":false,"secret_leak":false,"malicious_patch":false,"reasons":[]}`
850+
fakeBinDir := writeFakeCopilotWithSink(t, copilotMarker, sinkJSON, 0)
851+
852+
code, stderr := runWithTestArgsCapture(t, []string{
853+
"threat-detect",
854+
"-output", outputPath,
855+
"-step-summary", summaryPath,
856+
artifactsDir,
857+
}, map[string]string{
858+
"PATH": fakeBinDir + string(os.PathListSeparator) + os.Getenv("PATH"),
859+
})
860+
861+
if code != exitSafe {
862+
t.Fatalf("run() exit code = %d, want %d; stderr:\n%s", code, exitSafe, stderr)
863+
}
864+
if !strings.Contains(stderr, "ignoring deprecated --step-summary") {
865+
t.Errorf("stderr missing the ignored --step-summary notice, got:\n%s", stderr)
866+
}
867+
if _, err := os.Stat(summaryPath); !os.IsNotExist(err) {
868+
t.Errorf("expected no step summary to be written to %s, stat err = %v", summaryPath, err)
869+
}
870+
}

specs/threat-detection-spec.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,10 @@ artifact inventory defined by TD-17b is surfaced on standard error (TD-20a) only
288288
and the conclusion verdict through the `conclude` diagnostics (TD-20d). The
289289
rendered prompt itself MUST NOT be surfaced: the detector reports only its
290290
metadata (byte count, resolved workflow name/description, custom-prompt
291-
provenance, scaffolding detection).
291+
provenance, scaffolding detection). For compatibility with hosts that still pass
292+
the removed `--step-summary <path>` option, the detector MUST accept that option,
293+
ignore its value, note on standard error that it was ignored, and MUST NOT treat
294+
it as a configuration error.
292295

293296
**TD-20d**: The `conclude` subcommand MUST write a human-readable diagnostic
294297
section to standard output that is sufficient, on its own, to explain the

specs/usage-spec.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ versions.
170170
| `--prompt-template <path>` | Override the embedded default prompt |
171171
| `--output <path>` | Write the JSON result to a file instead of stdout |
172172
| `--retries <n>` | Retries for malformed detection outputs (default `1`) |
173+
| `--step-summary <path>` | Deprecated and ignored; accepted only for compatibility with hosts that still pass it (per TD-20c) |
173174
| `--version` | Print version and exit |
174175

175176
---

0 commit comments

Comments
 (0)