Skip to content

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

Open
yakimoto wants to merge 11 commits into
mainfrom
ci/1747-public-repo-guard-body-scan
Open

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

Conversation

@yakimoto

@yakimoto yakimoto commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

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 CI behavior and trusted-script sourcing on privileged review events; misconfiguration of vars.GUARD_PRIVATE_REPOS is designed to fail closed, but the new surface area warrants careful branch-protection alignment for the new check job.

Overview
Extends public-repo-guard so GitHub title/body text (PRs, issues, comments, and review summaries) is scanned server-side, not only the published tree. A new body-guard job materializes untrusted text from the event payload via jq and runs body-policy.sh, which flags credential-shaped strings, infra markers, and private-repo names only when paired with operational detail (~140 chars)—so bare cross-repo references stay allowed unlike content-policy.sh on the tree.

The guard job gains review-event hardening: on pull_request_review / pull_request_review_comment, gate executables (gitleaks.toml, policy scripts) are pinned from the default branch so fork PRs cannot supply the scanner. Triggers now include edited on PRs and bodies; per-job concurrency replaces workflow-level grouping (tree scans cancel in-flight on the same SHA; body scans do not). actions/checkout is bumped to v7.0.1; body-policy.test.sh runs in CI as a self-test.

Reviewed by Cursor Bugbot for commit a5711c9. 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 2a09911.

…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: Pro Plus

Run ID: 985b4281-85b6-4d35-9daa-9a9780669e09

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.

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.

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)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants