Skip to content

Prevent secrets from bypassing redaction in patch and bundle artifacts - #50778

Merged
pelikhan merged 7 commits into
mainfrom
copilot/prevent-secrets-redaction-bypass
Aug 6, 2026
Merged

pelikhan merged 7 commits into
mainfrom
copilot/prevent-secrets-redaction-bypass

Conversation

Copilot AI commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

redact_secrets.cjs did not scan .patch files, so secrets written into git patches could be uploaded unredacted. step_order_validation.go incorrectly asserted both .patch and .bundle were runtime-covered, creating a false compile-time guarantee. Binary .bundle files were also included in downloadable artifacts despite being unsafe to text-scan.

Changes

  • redact_secrets.cjs — Add .patch to targetExtensions so patch files are redacted before upload alongside other text formats.

  • compiler_yaml_post_agent.go — Remove TmpAwBundleGlob from artifact collection. Binary git bundles cannot be safely scanned as UTF-8 and must not be uploaded as downloadable artifacts.

  • step_order_validation.go — Sync scannedExtensions with the actual runtime contract: add .md, .mdx, .yml; drop .bundle. Add a comment noting this list must track targetExtensions in redact_secrets.cjs.

  • compiler_artifacts_test.go — Flip the bundle assertion to verify .bundle is not included in artifact uploads.

  • redact_secrets.test.cjs — Add two new tests for .patch file redaction: exact-value secret replacement and built-in credential pattern (GitHub PAT) detection.


Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 22.6 AIC · ⊞ 5.9K · ◷
Comment /souschef to run again

…ifacts

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Prevent secrets from bypassing redaction in patch and bundle artifacts Prevent secrets from bypassing redaction in patch and bundle artifacts Aug 6, 2026
Copilot AI requested a review from pelikhan August 6, 2026 05:42
@pelikhan
pelikhan marked this pull request as ready for review August 6, 2026 05:45
Copilot AI balanced review requested due to automatic review settings August 6, 2026 05:45
@github-actions

github-actions Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

@github-actions

github-actions Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

✅ Design Decision Gate 🏗️ completed the design decision gate check.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

No ADR enforcement needed: PR #50778 does not have the 'implementation' label and has only 10 new lines of code in business logic directories (threshold: 100).

@github-actions

github-actions Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

✅ PR Code Quality Reviewer completed the code quality review.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

@github-actions

github-actions Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

✅ Test Quality Sentinel completed test quality analysis.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Hardens artifact secret handling by redacting patch files and excluding unscannable git bundles.

Changes:

  • Adds .patch secret scanning and regression tests.
  • Excludes binary bundles from unified artifacts.
  • Aligns compiler validation with text-scanning extensions.
Show a summary per file
File Description
actions/setup/js/redact_secrets.cjs Adds patch scanning.
actions/setup/js/redact_secrets.test.cjs Tests patch redaction.
pkg/workflow/compiler_yaml_post_agent.go Excludes bundle artifacts.
pkg/workflow/compiler_artifacts_test.go Verifies bundle exclusion.
pkg/workflow/step_order_validation.go Updates scanned extensions.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 5/5 changed files
  • Comments generated: 2
  • Review effort level: Balanced


// Find all target files in /tmp/gh-aw and ${RUNNER_TEMP}/gh-aw directories
const targetExtensions = [".txt", ".json", ".log", ".md", ".mdx", ".yml", ".jsonl"];
const targetExtensions = [".txt", ".json", ".log", ".md", ".mdx", ".yml", ".jsonl", ".patch"];
Comment on lines +86 to +89
// Bundle files are binary git bundles that cannot be safely text-scanned for
// secrets. They are excluded from the downloadable artifact.
// The artifact upload step already sets if-no-files-found: ignore, so excluding
// the bundle glob here is safe even when no bundle files exist.
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

Excellent work! 🎉 This PR prevents a critical vulnerability where secrets in git patches could bypass redaction during artifact uploads.

What looks great:

  • ✅ Adds .patch file scanning to the text-redaction pipeline
  • ✅ Excludes binary .bundle files from artifact uploads entirely (safe-by-design)
  • ✅ Syncs compile-time validation with runtime redaction coverage
  • ✅ Comprehensive test coverage for both exact-value secrets and built-in credential patterns (GitHub PAT detection)
  • ✅ Clear, focused diff that addresses all acceptance criteria from Prevent secrets from bypassing redaction in patch and bundle artifacts #50771
  • ✅ Well-documented changes with helpful comments about the security rationale

The PR is ready for maintainer review. All checks pass, tests cover the new functionality, and the implementation is sound.

Generated by ✅ Contribution Check · auto · 53.8 AIC · ⊞ 8.7K · ◷

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

Skills-Based Review 🧠

Applied /diagnosing-bugs and /tdd — two observations raised as inline comments; overall the fix is well-scoped and correct.

📋 Key Themes & Highlights

Key Themes

  • Extension list drift risk — step_order_validation.go now adds .md/.mdx/.yml to scannedExtensions without documenting the rationale; the comment pointing to redact_secrets.cjs helps but a brief "why" would seal it.
  • Fragile test harness — the eval()+string-replace approach for the .patch tests can silently no-op if the source string drifts; worth a guard assertion.

Positive Highlights

  • ✅ The core fix is minimal and precise: one character class added to targetExtensions.
  • ✅ Binary .bundle files are now correctly excluded from artifact uploads with clear reasoning in comments.
  • ✅ Two meaningful regression tests added for the exact vulnerability scenario (exact-value secret + GitHub PAT pattern).
  • ✅ Compile-time guarantee in step_order_validation.go now accurately reflects the runtime contract.
  • ✅ Existing test flipped cleanly to assert the corrected behaviour.
> 🧠 *Reviewed using Matt Pocock's skills by [Matt Pocock Skills Reviewer](https://github.com/github/gh-aw/actions/runs/31075085067)* · sonnet46 · 30.3 AIC · ⊞ 7.1K > Comment /matt to run again

scannedExtensions := []string{".txt", ".json", ".log", ".md", ".mdx", ".yml", ".jsonl", ".patch"}
if slices.Contains(scannedExtensions, ext) {
return true
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/diagnosing-bugs] The new scannedExtensions silently adds .md, .mdx, and .yml — absent from the old list — changing what isPathScannedBySecretRedaction returns for those extensions. If any caller uses this function to reject certain paths, this is a silent behavioural change worth documenting.

💡 Suggestion

Add a brief comment explaining why .md/.mdx/.yml were added (they already appear in redact_secrets.cjs) to prevent future reviewers from removing them. Verify all callers of isPathScannedBySecretRedaction to ensure the additions are safe.

@copilot please address this.

const redacted = fs.readFileSync(patchFile, "utf8");
expect(redacted).not.toContain("my-patch-secret-value");
expect(redacted).toContain("***REDACTED***");
}),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] Both .patch tests use eval() to monkey-patch findFiles by string-replacing the source. This is fragile: any whitespace change in redact_secrets.cjs will silently break the replacement and the test will pass vacuously (no files found, nothing to redact).

💡 Suggestion

Consider asserting that at least one file was processed by checking a side-effect (e.g. mockCore.info called with the file path) so the test fails loudly if findFiles substitution breaks. Alternatively, extract findFiles as an injectable dependency so tests can pass a test double without string replacement.

@copilot please address this.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

Review: Prevent secrets from bypassing redaction in patch and bundle artifacts

The core security fix is correct and well-structured: adding .patch to targetExtensions closes a real redaction gap, removing .bundle from artifacts is the right call for binary-safe text scanning, and the tests are a solid addition.

One non-blocking issue flagged inline:

threat_detection_steps.go still copies aw-*.bundle files into /tmp/gh-aw/threat-detection/ (lines 196–200). The PR's rationale — bundles are binary, can't be safely UTF-8 decoded — applies equally here. If the threat detection LLM reader ingests those files as text, it receives garbled binary content. This should either remove the bundle-copy loop or add a comment explaining why binary bundles are intentionally forwarded to the detection context.

Everything else (extension list sync in step_order_validation.go, flipped test assertion in compiler_artifacts_test.go, new JS tests) looks correct.> 🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 43.8 AIC · ⊞ 5.3K

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

🧪 Test Quality Sentinel Report

✅ Test Quality Score: 90/100 — Excellent

Analyzed 3 test(s): 3 design, 0 implementation, 0 violation(s).

📊 Metrics (3 tests)
Metric Value
Analyzed 3 (Go: 1, JS: 2)
✅ Design 3 (100%)
⚠️ Implementation 0 (0%)
Edge/error coverage 3 (100%)
Duplicate clusters 0
Inflation ⚠️ Yes — redact_secrets.test.cjs +33 vs prod +1 (33:1)
🚨 Violations 0
Test File Classification Issues
it("should redact secrets from .patch files ...") redact_secrets.test.cjs behavioral_contract, design_test, high_value None
it("should redact built-in credential patterns from .patch files") redact_secrets.test.cjs behavioral_contract, design_test, high_value None
Modified bundle assertion compiler_artifacts_test.go behavioral_contract, design_test, high_value None
⚠️ Flagged Tests (1 — inflation only)

redact_secrets.test.cjs — Test inflation: +33 test lines vs +1 production line (33:1 ratio > 2:1 threshold). This is expected: the tests require filesystem setup, script evaluation, and multiple assertions per scenario. The coverage is genuine and the inflation is justified by security-critical scope. No action required.

Verdict

✅ Passed. 0% implementation tests (threshold: 30%). Both JS tests enforce the security contract that .patch files are scanned and redacted before upload — exact-value and built-in credential patterns. The modified Go test correctly inverts the bundle assertion to verify binary .bundle files are excluded from artifact uploads. All 3 tests are high-value behavioral contracts covering the exact vulnerability fixed in this PR.

🧪 Test quality analysis by Test Quality Sentinel · sonnet46 · 40.9 AIC · ⊞ 7.7K · ◷
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Test Quality Sentinel: 90/100. 0% implementation tests (threshold: 30%).

@pelikhan

pelikhan commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

@copilot bundle files are required downstream for pull requests so keep those

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

REQUEST_CHANGES — a critical functional regression: excluding .bundle files from the unified artifact appears to silently break the default patch-format: bundle transport for push_to_pull_request_branch/create_pull_request whenever the safe_outputs job needs to apply changes (the bundle file is generated in the agent job and can only reach the downstream job via this artifact).

Themes
  • The .patch redaction fix and the .bundle scanned-extensions sync in step_order_validation.go are correct and well-targeted.
  • The bundle-artifact removal in compiler_yaml_post_agent.go solves a real security gap (binary files can't be safely UTF-8-scanned) but does so by silently dropping a feature (bundle transport) rather than fixing the scanning gap or explicitly deprecating/warning about bundle-format in cross-job scenarios.
  • Test coverage for the bundle removal is purely negative (asserts the glob is absent) and does not verify the end-to-end behavior of bundle-format workflows post-change.
> 🔎 *Code quality review by [PR Code Quality Reviewer](https://github.com/github/gh-aw/actions/runs/31075085084)* · auto · 98.1 AIC · ⊞ 7.8K > Comment /review to run again

// Bundle files are binary git bundles that cannot be safely text-scanned for
// secrets. They are excluded from the downloadable artifact.
// The artifact upload step already sets if-no-files-found: ignore, so excluding
// the bundle glob here is safe even when no bundle files exist.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the bundle glob from the unified artifact breaks git-bundle transport for non-staged push_to_pull_request_branch/create_pull_request — the bundle is only produced in the agent job and consumed via this artifact by a separate job.

// Bundle files are binary git bundles that cannot be safely text-scanned for
// secrets. They are excluded from the downloadable artifact.
// The artifact upload step already sets if-no-files-found: ignore, so excluding
// the bundle glob here is safe even when no bundle files exist.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This removes the only mechanism shipping git-bundle files to the safe_outputs/detection jobs, silently breaking the default patch-format: bundle transport whenever a checkout is actually needed in a separate job.

💡 Details and fix

generate_git_bundle.cjs writes /tmp/gh-aw/aw-*.bundle inside the agent job (see safe_outputs_handlers.cjs calling generateGitBundle for both create_pull_request and push_to_pull_request_branch). The safe_outputs job runs as a separate GitHub Actions job and only gets access to agent-job files by downloading the unified agent artifact (buildAgentOutputDownloadSteps / patch artifact download in compiler_safe_outputs_job.go). push_to_pull_request_branch.cjs and create_pull_request.cjs both look for the bundle at that path and, since patch-format: bundle is the default, will silently fall back to patch transport (losing merge topology / per-commit metadata) any time the bundle actually exists but was never uploaded — which, after this change, is always, because TmpAwBundleGlob was dropped from collectArtifactPaths.

The stated rationale ("binary bundles cannot be safely text-scanned") is a real constraint, but the fix removes the feature instead of solving the scanning problem. Options:

  • Keep the bundle glob in the artifact but exclude it from the redact_secrets text scan (a binary file cannot be treated as UTF-8 text), while adding a compensating control such as base64/binary-safe secret scanning, or
  • Explicitly disable/deprecate patch-format: bundle for non-staged flows and document that only am/patch format is supported cross-job, with a clear compile-time warning/error.

As written, this is a silent functional regression with no test coverage — compiler_artifacts_test.go only asserts the bundle glob is absent, not that bundle-format cross-job pushes still work end-to-end.

Comment thread pkg/workflow/compiler_artifacts_test.go Outdated
if !strings.Contains(uploadSection, "/tmp/gh-aw/aw-*.bundle") {
t.Error("Expected '/tmp/gh-aw/aw-*.bundle' in unified artifact upload when threat detection is enabled with staged push-to-pull-request-branch")
if strings.Contains(uploadSection, "/tmp/gh-aw/aw-*.bundle") {
t.Error("Expected '/tmp/gh-aw/aw-*.bundle' to be excluded from unified artifact upload (binary bundles cannot be safely text-scanned for secrets)")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assertion only proves the bundle glob is absent — it does not cover whether bundle-format transport (the default) still functions correctly across jobs, so it cannot catch the regression flagged above.

💡 Details

Flipping !strings.Contains(...) to strings.Contains(...) correctly encodes the new intended behavior (bundle glob excluded), but it's a purely negative assertion. There's no test verifying that a workflow configured with patch-format: bundle and a non-staged push_to_pull_request_branch/create_pull_request actually delivers the bundle file to the safe_outputs job (or that it now correctly falls back to am/patch format, if that's the intended new behavior). Consider adding an integration-style test that compiles a bundle-format workflow and asserts the resulting job graph either (a) still ships the bundle via some other channel, or (b) explicitly forces patch-format to am / emits a compile warning when checkout is required outside the agent job.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Comment thread pkg/workflow/step_order_validation.go Outdated
// .bundle files are binary git bundles produced when patch-format: bundle is
// configured. They cannot be safely scanned as UTF-8 text by redact_secrets, but
// they are required downstream to apply changes while preserving merge topology,
// so they are intentionally allowed through artifact uploads unscanned.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot they are generated from the same git as the patch so the patch scanning is enough

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the comments to reflect this: bundles are built from the same git commit range as the accompanying .patch (via generateGitBundle calling generateGitPatch), so the .patch scan already covers the underlying diff content and no separate bundle scan is needed.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@copilot bundle files are required downstream for pull requests so keep those

Restored the .bundle glob in the unified artifact upload. isPathScannedBySecretRedaction now accurately reports .bundle as unscanned, and a separate isKnownUnscannedButAllowedForUpload check explicitly allows it through with a documented rationale, so we don't falsely claim bundles are text-scanned. Done in c8f... (latest push).

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

@copilot Thanks for the update. Please run the pr-finisher skill to address the remaining review feedback before maintainer pickup:

  • Review latest unresolved review notes, especially the scanner/extension-list drift note and the threat-detection bundle handling follow-up.
  • Re-run any needed targeted validation after the latest push.
  • If everything is addressed, summarize what changed and call out any remaining maintainer-only follow-up.

Run: https://github.com/github/gh-aw/actions/runs/31076105335

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 22.6 AIC · ⊞ 5.9K · ◷
Comment /souschef to run again

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

[!WARNING]
Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

...

Both items were already addressed in the latest commits before this comment:

  • Scanner/extension-list drift: scannedExtensions in step_order_validation.go and targetExtensions in redact_secrets.cjs are already in sync (.txt, .json, .log, .md, .mdx, .yml, .jsonl, .patch).
  • Bundle handling follow-up: .bundle is restored in the unified artifact upload (per @pelikhan's request), with isKnownUnscannedButAllowedForUpload as a separate, explicitly-documented allowance from the secret-scan check (isPathScannedBySecretRedaction), and the rationale comment clarifies bundles share the same git range as the scanned .patch.

Verified with targeted Go tests (pkg/workflow step-order/artifact/patch tests) — all passing. No further code changes needed; working tree is clean.

Copilot AI requested a review from gh-aw-bot August 6, 2026 06:23
@pelikhan
pelikhan merged commit 868fd80 into main Aug 6, 2026
40 checks passed
@pelikhan
pelikhan deleted the copilot/prevent-secrets-redaction-bypass branch August 6, 2026 06:38
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.86.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Prevent secrets from bypassing redaction in patch and bundle artifacts

4 participants