Skip to content

ci: scan issue and comment bodies — this repo has never scanned one - #64

Merged
yakimoto merged 15 commits into
mainfrom
ci/1747-public-repo-guard-body-scan
Sep 8, 2026
Merged

ci: scan issue and comment bodies — this repo has never scanned one#64
yakimoto merged 15 commits into
mainfrom
ci/1747-public-repo-guard-body-scan

Conversation

@yakimoto

@yakimoto yakimoto commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

User description

This repo's public-repo-guard has never scanned a single issue or comment body.

Measured across all 28 public wave-av repos (wave-av/claude-workstation#1747, #1794): two coverage shapes satisfy the one required check name Secrets + content policy.

repos triggers jobs
27 pull_request, push, workflow_dispatch guard
1 + issues, issue_comment + body-guard

This repo is in the 27. All 28 report the same green check — because a required check asserts that something named X passed, never what X examined.

The outlier is wave-moq-edge, and its own comment says why it matters:

edited matters as much as opened: a body can be made to leak long after the PR is first raised, and until this workflow covered it, nothing ever re-scanned.

That gap was not theoretical there: a PR was blocked for naming a private repo in wrangler.toml while the very same name, with more operational detail attached, sat unchallenged in its body.

What lands

Three files — the bundle the workflow's own header names, minus what this repo already has (.gitleaks.toml and content-policy.sh are already vendored, and are checked as prerequisites; a repo missing either is refused rather than half-installed):

.github/workflows/public-repo-guard.yml               replaced (72 -> 163 lines)
scripts/public-repo-guard/body-policy.sh              new, mode 100755
scripts/public-repo-guard/tests/body-policy.test.sh   new, mode 100755

The workflow's header names four files as the install unit but executes a fifthtests/body-policy.test.sh, in its own self-test step. Omitting it installs a workflow that fails on a step nobody read, so the manifest ships it. Modes are preserved via the git trees API; the contents API creates 100644 regardless, which would silently break running these scripts as executables.

Planned by governance/lib/vendor-bundle.mjs (claude-workstation#1850) against a checked-in manifest, not by ad-hoc shell.

One deliberate divergence from the reference, stated rather than silent

The shipped workflow is wave-moq-edge's with actions/checkout bumped from v5.0.1 to v7.0.1 (3d3c42e5aac5ba805825da76410c181273ba90b1), the pin already used by claude-workstation's own gate.

Copying verbatim was checked first and rejected on evidence: of the 18 target repos, 17 carry a byte-identical guard, and wave-realtime-edge already runs v7.0.0 — so a verbatim copy would have downgraded it, and shipped a stale pin to the other 17. A separate PR brings the reference itself up to the same pin.

Honest about what this can and cannot do

On a PR this PREVENTS the merge. On an issue or comment the text is already public the moment it posts, so this is DETECTION: it says go redact, fast. Only a client-side pre-write hook stops that class before publication.

Also inherited from the reference: concurrency moves from workflow-level to per job, because the two jobs want opposite behaviour. A workflow-level group forced one policy on both, and rapid body edits cancelled the tree job repeatedly — every cancelled check-run stays attached to the commit, so the PR reported UNSTABLE while the live runs were green.

The body gate ships with its own fixtures and runs them in CI. Its negative cases are the load-bearing half: a leak gate that blocks legitimate cross-repo references gets switched off, and then it protects nothing.

Refs wave-av/claude-workstation#1747.


Note

Medium Risk
Changes security-gate behavior and CI triggers (including fail-closed bootstrap and review-event trust boundaries); misconfigured GUARD_PRIVATE_REPOS or the install window could block merges or events until fixed.

Overview
Extends public-repo-guard so publicly visible discussion text is scanned the same way the repo tree already is, closing the gap where secrets and internal detail could live in PR/issue/comment/review bodies (including after edited events) without server-side checks.

A new body-guard job materializes title/body text from the GitHub event payload (via jq, never shell-interpolated) and runs body-policy.sh, which ripgrep-scans for credential-shaped strings (no exemptions), infra markers, and private repo names only when paired with operational detail—unlike the tree policy, bare cross-repo references stay allowed. The existing guard job keeps the gitleaks + content-policy.sh tree scan but gains per-job concurrency, actions/checkout v7.0.1, review-event pinning of gate scripts to the default branch so fork PRs cannot substitute policy code on privileged review runs, and a CI self-test via body-policy.test.sh.

Install docs now list five vendored files; bootstrap paths fail closed for fork PRs when body-policy.sh is not yet on the default branch, and missing vars.GUARD_PRIVATE_REPOS in CI fails the proximity rule instead of silently passing.

Reviewed by Cursor Bugbot for commit 7929511. Bugbot is set up for automated code reviews on this repo. Configure here.

View with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is enabled.

Note

Scan PR/issue/comment/review bodies for credentials and internal markers in public-repo-guard

  • Adds body-policy.sh, a new ripgrep-based script that scans untrusted body text for credential-shaped strings (Stripe, Anthropic, GitHub PAT, AWS AKID, private keys, etc.), internal-only markers, operator paths, and private repo names near operational detail tokens.
  • Extends the public-repo-guard.yml workflow with a new body-guard job triggered by issues, issue comments, PR reviews, and review comments; materializes event body/title text via jq and runs body-policy.sh against it.
  • On review events, gate executables are pinned to the default branch via sparse checkout so untrusted PR modifications cannot alter the policy scripts being run.
  • Adds body-policy.test.sh with hermetic fixture tests covering blocking, passing, and fail-closed cases; the workflow runs these as a self-test step.
  • Risk: the workflow now fails closed on unrecognized event payloads or missing trusted scripts during bootstrap, which could block legitimate events if the gate repo is misconfigured.

Macroscope summarized 134669a.

Summary by Sourcery

Extend public-repo-guard to detect sensitive content across all publicly visible pull request, issue, comment, and review text while keeping trusted scanning controls and validation fail-closed.

New Features:

  • Extend public-repo-guard to scan pull request, issue, comment, and review titles and bodies for secrets and internal information.
  • Add body-policy scanning with credential, infrastructure, internal-marker, and private-repository operational-detail checks.

Bug Fixes:

  • Close the gap where publicly visible discussion content was not scanned or rescanned after edits.
  • Prevent untrusted pull request policy scripts from being executed during privileged review-event runs.

Enhancements:

  • Use event-specific job concurrency and fail-closed handling for missing trusted scripts, invalid payloads, scanner errors, and CI configuration.
  • Pin gate executables to the default branch for review events while preserving bootstrap support for the installation change.
  • Redact matched content from workflow annotations while reporting violation locations.

CI:

  • Trigger public-repo-guard for edited pull requests, issues, issue comments, reviews, and review comments.
  • Run hermetic body-policy fixture tests as part of the guard job.
  • Upgrade the pinned actions/checkout version to v7.0.1.

Tests:

  • Add fixture coverage for blocking detections, allowed cross-references and policy discussions, credential exemption behavior, and fail-closed configuration paths.

PR Type

Enhancement


Description

  • Added body content scanning to detect secrets and internal info in PRs, issues, and comments

  • Introduced new scripts for body policy enforcement and testing

  • Updated workflow to include dedicated body scanning job


Diagram Walkthrough

flowchart LR
  A["public-repo-guard.yml"] --> B["body-policy.sh"]
  A --> C["body-policy.test.sh"]
  B --> D["secret detection"]
  B --> E["internal marker detection"]
  B --> F["private repo proximity check"]
Loading

File Walkthrough

Relevant files
Configuration changes
public-repo-guard.yml
Enhanced workflow to include body content scanning             

.github/workflows/public-repo-guard.yml

  • Added new 'body-guard' job to scan PR/issue/comment bodies
  • Updated concurrency controls for body scanning
  • Added logic to pin gate executables to default branch for review
    events
  • Improved event type coverage including pull_request_review and
    issue_comment
+239/-6 
Enhancement
body-policy.sh
New body content policy enforcement script                             

scripts/public-repo-guard/body-policy.sh

  • Implemented secret detection for credentials and API keys
  • Added internal marker detection for sensitive content
  • Created private repo proximity check with operational detail analysis
  • Included line-level exemptions for allowed patterns
+183/-0 
Tests
body-policy.test.sh
Test suite for body content policy checks                               

scripts/public-repo-guard/tests/body-policy.test.sh

  • Created fixture-based test suite for body policy checks
  • Added test cases for both blocking and non-blocking scenarios
  • Implemented validation for proper error handling
  • Included tests for configuration validation
+150/-0 

…ment body

Measured across all 28 public wave-av repos (claude-workstation#1747, #1794):
TWO coverage shapes satisfy the one required check name `Secrets + content policy`.

  27 repos  triggers: pull_request, push, workflow_dispatch      jobs: guard
   1 repo   triggers: + issues, issue_comment                    jobs: + body-guard

This repo is in the 27. All 28 report the same green check.

The outlier is wave-moq-edge, and its own comment says why it matters:

  "`edited` matters as much as `opened`: a body can be made to leak long after the
   PR is first raised, and until this workflow covered it, nothing ever re-scanned."

A PR/issue/comment BODY is exactly as world-readable as the tree, and until now it
was scanned by nothing server-side. That gap was not theoretical on wave-moq-edge: a
PR was blocked for naming a private repo in wrangler.toml while the very same name,
with more operational detail attached, sat unchallenged in its body.

WHAT LANDS HERE — the bundle the workflow's own header names, minus what this repo
already has (.gitleaks.toml and content-policy.sh are already vendored):

  .github/workflows/public-repo-guard.yml          replaced (73 -> 163 lines)
  scripts/public-repo-guard/body-policy.sh         new, mode 100755
  scripts/public-repo-guard/tests/body-policy.test.sh  new, mode 100755

Copied from wave-moq-edge, which has run this shape in production. Modes preserved
via the git trees API — the contents API would have created both scripts 100644.

HONEST ABOUT WHAT IT CAN DO. On a PR this PREVENTS the merge. On an issue or comment
the text is already public the moment it posts, so this is DETECTION: it says go
redact, fast. Only a client-side pre-write hook stops that class before publication.

Also inherited from the reference: concurrency moves from workflow-level to PER JOB,
because the two jobs want opposite behaviour. A workflow-level group forced one
policy on both, and rapid body edits cancelled the tree job repeatedly — every
cancelled check-run stays attached to the commit, so the PR reported UNSTABLE while
the live runs were green.

The body gate ships with its own fixtures and runs them in CI. Its NEGATIVE cases are
the load-bearing half: a leak gate that blocks legitimate cross-repo references gets
switched off, and then it protects nothing.

Refs wave-av/claude-workstation#1747.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@yakimoto yakimoto added the rr:skip-coderabbit RF.P1 reviewer routing (#1039) label Aug 6, 2026
@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_263f3bd0-3b45-4774-bc37-17387c394f59)

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are limited based on label configuration.

🚫 Excluded labels (none allowed) (1)
  • rr:skip-coderabbit

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Team

Run ID: 1d5917c3-73ff-4ad3-b313-b88580e3cef2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Running ultrareview automatically — Adding a repo-wide body-scanning security gate touches CI/CD behavior on every PR/issue/comment; a subtle regex or allowlist bug could block all merges or let a leak through, so this warrants a slower multi-pass review.. I'll post findings when complete.

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 6, 2026
@macroscopeapp

macroscopeapp Bot commented Aug 6, 2026

Copy link
Copy Markdown

Approvability

Verdict: Needs human review

Unable to check for correctness in 2a09911. This PR introduces a significant new security scanning feature with unresolved review comments identifying a potential detection bug (word boundary issue in proximity rule) and a security gap (.guardignore from untrusted tree can neuter scans in privileged runs). These substantive concerns warrant human review.

No code changes detected at 134669a. Prior analysis still applies.

You can customize Macroscope's approvability policy. Learn more.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

CI: scan PR/issue/comment bodies with public-repo-guard body-guard job

✨ Enhancement 🧪 Tests ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add body-guard job to scan PR/issue/comment titles and bodies on create/edit events.
• Keep tree scanning in guard job, with per-job concurrency to avoid unstable check-runs.
• Introduce body-policy.sh plus fixture tests to fail closed and avoid false positives.
Diagram

graph TD
  Epr(["PR events"]) --> WF["public-repo-guard workflow"] --> Jg["guard job"] --> Cp["content-policy.sh"]
  Epush(["Push/dispatch"]) --> WF["public-repo-guard workflow"] --> Jg["guard job"] --> Cp["content-policy.sh"]
  Ebody(["Issue/comment events"]) --> WF["public-repo-guard workflow"] --> Jb["body-guard job"] --> Bp["body-policy.sh"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Extract body-policy into a reusable composite action
  • ➕ Centralizes the policy and test harness for reuse across repos
  • ➕ Simplifies workflow YAML and reduces per-repo drift
  • ➖ Requires action versioning and distribution, adding release overhead
  • ➖ Still needs careful permissions/event handling per repo
2. Use GitHub API fetch + github-script instead of jq on event payload
  • ➕ Can normalize payload shapes across event types via a single code path
  • ➕ Easier to enrich context (e.g., links to offending body) without shell parsing
  • ➖ More dependency on runtime JS and Octokit semantics
  • ➖ Higher risk of accidentally logging or interpolating untrusted content if not carefully handled
3. Fold body scanning into the existing guard job
  • ➕ Fewer jobs/checks to reason about and less duplication of setup steps
  • ➖ Harder to express the opposite concurrency semantics (cancel tree scans; never cancel body scans)
  • ➖ Would pay tree checkout cost on comment/issue events unless heavily conditional

Recommendation: The PR’s approach (separate body-guard job with sparse checkout, strict payload-shape validation, and fail-closed scanning) is the best fit for the stated goals: it avoids pull_request_target, minimizes checkout cost on comment events, and allows distinct concurrency semantics per surface area. If this pattern is rolled out broadly, consider the composite-action extraction later to reduce per-repo maintenance.

Files changed (3) +342 / -5

Enhancement (1) +139 / -0
body-policy.shIntroduce body content-policy scanner for PR/issue/comment text +139/-0

Introduce body content-policy scanner for PR/issue/comment text

• Adds a ripgrep-based policy scanner that reads untrusted body text from a file, applies allowlists, and emits redacted annotations with line numbers only. Implements blocking rules for credential formats and internal identifiers, plus a proximity-based rule for private repo names near operational detail, and fails closed on scanner errors.

scripts/public-repo-guard/body-policy.sh

Tests (1) +108 / -0
body-policy.test.shAdd fixture-only tests for body-policy behavior and redaction +108/-0

Add fixture-only tests for body-policy behavior and redaction

• Adds a hermetic fixture test runner that validates both blocking and non-blocking cases, including regression coverage for quoted “internal-only” mentions. Verifies the script fails closed on missing/invalid input and ensures annotations never echo matched secret-like text.

scripts/public-repo-guard/tests/body-policy.test.sh

Other (1) +95 / -5
public-repo-guard.ymlAdd body-guard job and expand triggers to scan edited bodies +95/-5

Add body-guard job and expand triggers to scan edited bodies

• Extends triggers to include issues and issue comments, and expands PR event types to include edits. Adds a new 'body-guard' job that materializes title/body from the event payload and runs a dedicated body policy scanner, while keeping the existing tree scan in 'guard' with job-specific concurrency and an updated checkout pin.

.github/workflows/public-repo-guard.yml

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 5 potential issues.

Open in Devin Review

Comment thread .github/workflows/public-repo-guard.yml Outdated
Comment thread scripts/public-repo-guard/body-policy.sh Outdated
Comment on lines +44 to +55
raw="$(rg -nP --no-filename -- "$re" "$FILE" 2>/dev/null)"; rc=$?
if (( rc >= 2 )); then
echo "::error title=public-repo-guard ($name)::ripgrep failed (exit $rc) scanning rule '$name' — failing closed."
exit 2
fi
# Filter with rg, not grep: BSD/macOS grep has no -P, so a `grep -P` allowlist
# silently errors out locally while working on GNU/CI — the gate would then
# disagree with itself depending on where it ran. rg is already required above.
local matches
matches="$(printf '%s' "$raw" \
| rg -vN -- 'guard:allow[[:space:]]+[^[:space:]]' \
| rg -vNiP -- "$ABOUT_THE_CONTROL" || true)"

@devin-ai-integration devin-ai-integration Bot Aug 6, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 apt-installed ripgrep on older Ubuntu has no PCRE2, which would fail the whole gate closed

Both new/existing Install ripgrep steps fall back to apt-get install ripgrep. I verified locally on Ubuntu 22.04 that the distro package (13.0.0-2ubuntu0.1) is built without PCRE2: rg -P exits 2 with "PCRE2 is not available in this build of ripgrep". Every rule in scripts/public-repo-guard/body-policy.sh uses rg -nP, and check() treats exit >= 2 as a scanner error and exits 2 — so on such a runner the body gate (and content-policy.sh, which has the same dependency) would fail closed on every event rather than scan anything. Running the fixture suite here reproduces exactly that: 25/29 fixtures fail with "ripgrep failed (exit 2)"; with a PCRE2-capable engine all 29 pass.

This is fine as long as ubuntu-latest keeps providing a PCRE2-enabled ripgrep (24.04 ships 14.x, which does). It is worth noting because the failure mode is a hard red on every PR/issue/comment, and because it makes the fixture suite unrunnable for contributors on older distros.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread .github/workflows/public-repo-guard.yml
Comment thread .github/workflows/public-repo-guard.yml
@qodo-code-review

qodo-code-review Bot commented Aug 6, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📜 Skill insights (0)

Grey Divider


Action required

1. Allowlist bypasses body scan ✓ Resolved 🐞 Bug ⛨ Security
Description
In body-policy.sh, every rule’s matches are filtered to drop lines containing guard:allow <reason>
or matching ABOUT_THE_CONTROL, so a real credential/token/private-key match on an exempt line can be
silently ignored and the job will report success.
Code

scripts/public-repo-guard/body-policy.sh[R53-55]

+  matches="$(printf '%s' "$raw" \
+    | rg -vN -- 'guard:allow[[:space:]]+[^[:space:]]' \
+    | rg -vNiP -- "$ABOUT_THE_CONTROL" || true)"
Relevance

●● Moderate

Allowlist bypass may be intentional for deployability; security tradeoff is subjective without local
precedent.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The check() function filters out any matching line containing guard:allow … or matching
ABOUT_THE_CONTROL before counting/reporting matches, and this filtering is used for every
subsequent credential rule. The fixtures explicitly assert that a line which would otherwise match
the private-repo proximity rule passes when guard:allow is present, demonstrating the bypass
mechanism is active.

scripts/public-repo-guard/body-policy.sh[20-22]
scripts/public-repo-guard/body-policy.sh[31-35]
scripts/public-repo-guard/body-policy.sh[53-56]
scripts/public-repo-guard/body-policy.sh[71-79]
scripts/public-repo-guard/tests/body-policy.test.sh[74-76]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`body-policy.sh` applies the `guard:allow` and `ABOUT_THE_CONTROL` line-level exemptions inside the shared `check()` helper for **all** rules, including high-confidence credential detectors (AWS AKID, GitHub PAT, private key header, etc.). This means a line can contain a real secret and still be removed from `matches`, causing a false-negative pass.

### Issue Context
This workflow is intended to detect/block sensitive content in PR/issue/comment text. Allowlisting is useful to keep the gate deployable for policy discussions/examples, but it should not suppress detection for credential/private-key formats.

### Fix Focus Areas
- scripts/public-repo-guard/body-policy.sh[37-69]
- scripts/public-repo-guard/body-policy.sh[71-86]
- scripts/public-repo-guard/tests/body-policy.test.sh[22-36]

### What to change
- Make allowlisting selective:
 - Either **do not apply** `guard:allow` / `ABOUT_THE_CONTROL` filtering for credential/private-key rules (e.g., `stripe-live-key`, `anthropic-key`, `github-pat`, `supabase-pat`, `aws-akid`, `private-key`).
 - Or perform a two-pass approach: run credential/private-key checks without exemptions; run “policy-discussion prone” rules (e.g., internal-marker, private-repo-ops) with exemptions.
- Add/adjust fixtures so at least one credential-shaped pattern combined with `guard:allow` still **BLOCKS**, preventing regressions.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Install list misses test ✓ Resolved 🐞 Bug ☼ Reliability
Description
The workflow header says to copy four files to install, but the workflow also runs
scripts/public-repo-guard/tests/body-policy.test.sh; following the documented install steps would
omit that file and cause CI to fail due to a missing script.
Code

.github/workflows/public-repo-guard.yml[R17-20]

#   .github/workflows/public-repo-guard.yml
#   .gitleaks.toml
#   scripts/public-repo-guard/content-policy.sh
+#   scripts/public-repo-guard/body-policy.sh
Relevance

●●● Strong

Keeping workflow install header consistent with executed scripts is a low-risk reliability/doc fix.

PR-#21

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The workflow’s install instructions list only four files, but later the guard job runs the
body-policy fixture test script. If that script is not copied during installation, the step will
fail with a missing file error.

.github/workflows/public-repo-guard.yml[16-20]
.github/workflows/public-repo-guard.yml[96-101]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The workflow’s “To install” comment lists only four files, but the workflow executes a fifth file: `scripts/public-repo-guard/tests/body-policy.test.sh`. If someone installs by following the header instructions, the workflow will fail at runtime.

### Issue Context
This repo includes the tests file, but the workflow header is intended as the install manifest for other repos.

### Fix Focus Areas
- .github/workflows/public-repo-guard.yml[16-20]
- .github/workflows/public-repo-guard.yml[96-101]

### What to change
- Update the header install instructions to include:
 - `scripts/public-repo-guard/tests/body-policy.test.sh`
- (Alternative) If you intentionally don’t want the tests shipped, remove/guard the self-test step so installs don’t require that file.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. AWS key fixture in tests 📘 Rule violation ⛨ Security
Description
The new fixture test constructs an AKIA... AWS access key ID value, which is a credential-like
secret pattern committed in source. Even if intended as a dummy, it risks violating the repository
policy against hard-coded secrets and can trigger secret scanners unnecessarily.
Code

scripts/public-repo-guard/tests/body-policy.test.sh[R57-59]

+AKID_FIXTURE="AKI""A1234567890ABCDEF"
+expect 1 'AWS access key id' \
+  "The failing job had ${AKID_FIXTURE} configured."
Relevance

●● Moderate

Credential-like fixtures often get adjusted, but this one is already split to avoid scanners;
outcome unclear.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2497924 prohibits committing hard-coded secrets or secret-like credential values.
The test file constructs an AKIA... AWS access key ID fixture (AKID_FIXTURE) intended to match
the scanner, which is a credential-like value embedded in source.

Rule 2497924: Disallow hard-coded secrets in source code
scripts/public-repo-guard/tests/body-policy.test.sh[57-59]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`scripts/public-repo-guard/tests/body-policy.test.sh` constructs an AWS access key ID fixture (an `AKIA...`-shaped credential) from string literals. The compliance rule disallows hard-coded secrets/credential-like values in committed source, even in tests.

## Issue Context
The test still needs a string that matches the `aws-akid` regex in `body-policy.sh`, but it should avoid embedding a credential-shaped full value directly in source.

## Fix Focus Areas
- scripts/public-repo-guard/tests/body-policy.test.sh[57-59]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context used
✅ Compliance rules (platform): 7 rules
✅ REVIEW.md
Review mode: ⚖️ Balanced: Downgraded extended -> standard: change is below the extended eligibility bar (hunks 5/18, lines 347/200; both must reach the floor). Router rationale: This is a security-sensitive CI/workflow change with substantial new shell logic across multiple independent paths, including event routing, untrusted payload handling, regex policy, fail-closed behavior, and fixture coverage; redundant review is warranted.

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment on lines +57 to +59
AKID_FIXTURE="AKI""A1234567890ABCDEF"
expect 1 'AWS access key id' \
"The failing job had ${AKID_FIXTURE} configured."

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

1. Aws key fixture in tests 📘 Rule violation ⛨ Security

The new fixture test constructs an AKIA... AWS access key ID value, which is a credential-like
secret pattern committed in source. Even if intended as a dummy, it risks violating the repository
policy against hard-coded secrets and can trigger secret scanners unnecessarily.
Agent Prompt
## Issue description
`scripts/public-repo-guard/tests/body-policy.test.sh` constructs an AWS access key ID fixture (an `AKIA...`-shaped credential) from string literals. The compliance rule disallows hard-coded secrets/credential-like values in committed source, even in tests.

## Issue Context
The test still needs a string that matches the `aws-akid` regex in `body-policy.sh`, but it should avoid embedding a credential-shaped full value directly in source.

## Fix Focus Areas
- scripts/public-repo-guard/tests/body-policy.test.sh[57-59]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread scripts/public-repo-guard/body-policy.sh Outdated
Comment thread .github/workflows/public-repo-guard.yml
@qodo-code-review

Copy link
Copy Markdown

Qodo Fixer

🍒 Ready to be cherry-picked — ✅ Merged (0) · ☑ Fixed (1)

Grey Divider

🔗 Fix PR: #65

This fix PR was closed automatically. Its branch is preserved so you can cherry pick the changes into the original PR.

Prompt for coding agent

This is an automated fix prepared on a separate branch (#65). It is NOT applied to this PR.
To use it: review Fix PR #65 (https://github.com/wave-av/sdk/pull/65), evaluate each change critically against your local context, and cherry-pick the changes that are correct into this branch. Do not accept them blindly.
Process — 1 fixed
  • ☑ Fixed: Allowlist bypasses body scan

…ted PRs

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
…he test file

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
cubic-dev-ai[bot]

This comment was marked as resolved.

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

…y from the default branch

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 3 new potential issues.

Open in Devin Review

Comment thread .github/workflows/public-repo-guard.yml Outdated
Comment on lines +196 to +201
if: >-
github.event_name == 'pull_request'
|| github.event_name == 'issues'
|| github.event_name == 'issue_comment'
|| github.event_name == 'pull_request_review'
|| github.event_name == 'pull_request_review_comment'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Issue/issue-comment failures attach a red check-run to the default branch

body-guard runs on issues and issue_comment, whose GITHUB_REF/GITHUB_SHA point at the default branch. A leaking issue comment therefore posts a FAILED Body content policy check-run against the latest commit on main. That is the intended detection signal, but it also means any tooling that reads the combined commit status of main (release automation, dashboards, deploy gates) will see main as failing because of text in an unrelated issue. Worth confirming nothing downstream keys off the default branch's commit status.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread .github/workflows/public-repo-guard.yml
Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

…mption-filter errors

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_33ecabf1-82a1-462a-80a3-388d038acf9b)

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 2 new potential issues.

Open in Devin Review

Comment on lines +167 to +169
elif [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then
echo "::error title=public-repo-guard (private-repo-ops)::GUARD_PRIVATE_REPOS resolved empty in CI — the private-repo proximity rule would silently not run. Set the org/repo Actions variable vars.GUARD_PRIVATE_REPOS; failing closed rather than reporting a pass that enforces nothing."
exit 2

@devin-ai-integration devin-ai-integration Bot Aug 6, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Missing GUARD_PRIVATE_REPOS now hard-fails, diverging from the tree gate's silent skip

content-policy.sh:101-110 silently skips the private-repo rule when GUARD_PRIVATE_REPOS is empty, including in CI. The new body gate instead exits 2 whenever GITHUB_ACTIONS=true and the variable resolves empty. The divergence is deliberate and documented, but it means the Body content policy job goes red on every PR, issue and comment in this repo unless vars.GUARD_PRIVATE_REPOS is actually set at org or repo level here — something the currently-green tree gate would not have revealed, since it just skips. Worth confirming the variable is configured for wave-av/sdk (and that org variables are exposed to fork-PR runs, otherwise fork PRs will always fail this job) before or immediately after merge.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread .github/workflows/public-repo-guard.yml
…dy-guard

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_63dc2fa0-88fb-4f5f-9e17-61b7606bdc55)

devin-ai-integration[bot]

This comment was marked as resolved.

… name-first proximity rule

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

Open in Devin Review

Comment on lines 168 to +172
- name: content policy (WAVE trade-secret / internal-leak gate)
env:
GUARD_PRIVATE_REPOS: ${{ vars.GUARD_PRIVATE_REPOS }}
run: bash scripts/public-repo-guard/content-policy.sh .
GATE_DIR: ${{ steps.gate.outputs.dir }}
run: bash "$GATE_DIR/scripts/public-repo-guard/content-policy.sh" .

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟨 Privileged review-event scan still honours scan-scope files taken from the untrusted pull request tree

On pull_request_review / pull_request_review_comment the guard job pins only the gate's executables (.gitleaks.toml, content-policy.sh) to the default branch, but the scan itself still runs against the checked-out PR tree and both scanners read scope-control files from that same untrusted tree: content-policy.sh appends every glob from a repo-root .guardignore to its exclude list (scripts/public-repo-guard/content-policy.sh:34-39), and gitleaks honours a .gitleaksignore at --source .. A pull request can therefore add .guardignore containing ** and make the pinned, trusted scanners report a clean tree.

(Refers to lines 161-172)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Honoring .guardignore/.gitleaksignore from the scanned tree is the gate's documented, diff-visible allowlist mechanism: any suppression file a PR adds is visible in the public diff under review, and the same suppression applies identically in the unprivileged pull_request run, so there is no privilege escalation specific to review events. This finding was reviewed and deliberately skipped in four prior passes for the same reason.

Comment on lines +288 to +306
- name: body policy (PR / issue / comment / review text)
env:
GUARD_PRIVATE_REPOS: ${{ vars.GUARD_PRIVATE_REPOS }}
run: |
set -euo pipefail
script="trusted/scripts/public-repo-guard/body-policy.sh"
if [ ! -f "$script" ]; then
if [ -f "bootstrap/scripts/public-repo-guard/body-policy.sh" ]; then
echo "::notice title=public-repo-guard (body-guard)::body-policy.sh is not on the default branch yet; bootstrap run using this same-repo PR's own copy."
script="bootstrap/scripts/public-repo-guard/body-policy.sh"
else
# No trusted copy and no same-repo bootstrap copy: this is a fork
# PR (or a non-PR event) during the bootstrap window. Refuse to
# grade a body with a scanner the untrusted tree supplies.
echo "::error title=public-repo-guard (body-guard)::body-policy.sh is not on the default branch and this event's tree is untrusted; refusing to execute the PR's own scanner. Merge the guard bundle to the default branch first."
exit 1
fi
fi
bash "$script" "$RUNNER_TEMP/bodyscan/body.txt"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

False positive: on issues/issue_comment events the bootstrap checkout (the only non-default-branch ref) is statically disabled by its step-level if (event must be pull_request/pull_request_review/pull_request_review_comment and same-repo), so line 306 only ever executes the default branch's copy or fails closed. The job also never writes to the Actions cache, so no poisoning vector exists.

@codeant-ai

codeant-ai Bot commented Sep 6, 2026

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Incremental review completed 7929511 Sep 08, 2026 · 02:12 02:12
✅ Incremental review completed 134669a Sep 07, 2026 · 23:51 23:51
✅ Incremental review completed e9f3385 Sep 06, 2026 · 22:45 22:45
✅ Reviewed your PR 23cb4fc Sep 06, 2026 · 20:00 20:02

@codeant-ai

codeant-ai Bot commented Sep 6, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@cursor

cursor Bot commented Sep 6, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_0532ed61-1cf9-4b5b-a7d9-0e52fea78646)

@codeant-ai codeant-ai Bot added the size:XL This PR changes 500-999 lines, ignoring generated files label Sep 6, 2026
Comment on lines +256 to +259
&& github.event.pull_request.head.repo.full_name == github.repository
with:
ref: ${{ github.event.pull_request.head.sha }}
path: bootstrap

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: During bootstrap, a same-repository PR can replace body-policy.sh, then use that modified scanner to approve its own body before the trusted copy reaches the default branch. [security]

Assessment: 🟠 Major · 🔁 Occurrence: Sometimes

Use CodeAnt Skill Fix in Cursor Fix in VSCode Claude

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** .github/workflows/public-repo-guard.yml
**Line:** 256:259
**Comment:**
	*Security: During bootstrap, a same-repository PR can replace `body-policy.sh`, then use that modified scanner to approve its own body before the trusted copy reaches the default branch.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

echo "::error title=public-repo-guard ($name)::ripgrep failed (exit $rc) applying the guard:allow exemption for rule '$name' — failing closed."
exit 2
fi
matches="$(printf '%s' "$matches" | rg -vNiP -- "$ABOUT_THE_CONTROL")"; rc=$?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The allowlist removes an entire matching line, so a line mentioning body-policy can also contain and suppress a private-repository name, secret binding, path, or infrastructure leak. [security]

Assessment: 🟠 Major · 🔁 Occurrence: Sometimes

Use CodeAnt Skill Fix in Cursor Fix in VSCode Claude

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** scripts/public-repo-guard/body-policy.sh
**Line:** 70:70
**Comment:**
	*Security: The allowlist removes an entire matching line, so a line mentioning `body-policy` can also contain and suppress a private-repository name, secret binding, path, or infrastructure leak.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@cursor

cursor Bot commented Sep 6, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_25ff9417-4b66-4c74-8954-d35c61e7a881)

@cursor

cursor Bot commented Sep 7, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_54cfb8e3-7bb4-46fa-99b1-8d09183a40e3)

sourcery-ai[bot]
sourcery-ai Bot previously approved these changes Sep 7, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sourcery assessment

Approved.

@yakimoto
yakimoto enabled auto-merge September 8, 2026 00:03
…uard-body-scan

# Conflicts:
#	.github/workflows/public-repo-guard.yml
@cursor

cursor Bot commented Sep 8, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_9a86bc5b-1ceb-469a-844b-0b86be53e493)

@yakimoto
yakimoto added this pull request to the merge queue Sep 8, 2026
Merged via the queue into main with commit b468e55 Sep 8, 2026
27 of 32 checks passed
@yakimoto
yakimoto deleted the ci/1747-public-repo-guard-body-scan branch September 8, 2026 02:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rr:skip-coderabbit RF.P1 reviewer routing (#1039) size:XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants