Skip to content

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

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

ci: scan issue and comment bodies — this repo has never scanned one#43
yakimoto wants to merge 19 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
Touches a required security merge gate and CI concurrency/check-run behavior, so misconfiguration could affect mergeability or leak detection. Changes are additive and fail-closed, which limits downside.

Overview
Closes a real coverage gap: PR, issue, and comment bodies are now scanned for credential and operational leaks, not just the published tree.

Adds body-policy.sh and a new Body content policy job triggered on PR open/edit, issues, and comments. It blocks credential formats, infra identifiers, unquoted internal markers, and private-repo names near operational detail — while allowing bare cross-repo references so the gate stays usable. Matched text is redacted in annotations; guard:allow and about-the-control lines can exempt non-credential hits.

Workflow updates: subscribe to edited/issues/issue_comment, move concurrency to per-job (tree cancels in progress; body does not), pin checkout to v7.0.1, and install a checksum-verified PCRE2 ripgrep. Fixture self-tests run in CI.

Reviewed by Cursor Bugbot for commit 75f4f7a. Configure here.


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

Review in cubic

Note

Add body content policy CI job to scan PR, issue, and comment bodies

  • Adds a new body-guard CI job in public-repo-guard.yml that triggers on pull_request, issues, and issue_comment events and runs body-policy.sh against materialized event bodies.
  • body-policy.sh scans for credential formats (Stripe, Anthropic, GitHub PATs, AWS keys, etc.) and infrastructure identifiers using PCRE2 ripgrep; credentials always block, infra identifiers can be allowlisted with guard:allow.
  • Adds fixture tests in body-policy.test.sh that run as part of the guard job and fail CI on regressions.
  • Ripgrep installation now pins a checksum-verified release to guarantee PCRE2 support when the preinstalled version lacks it.
  • Fixes oasdiff --version invocation in foundation-gate.yml, replacing the non-existent version subcommand.

Macroscope summarized 4ac6535.

…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_c47dab26-9abf-4f10-9a58-a27ba576d46b)

@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: 539badb2-d20c-4010-991e-5bba3b4a4cf8

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.

@macroscopeapp

macroscopeapp Bot commented Aug 6, 2026

Copy link
Copy Markdown

Approvability

Verdict: Needs human review

New CI gate feature adding body content scanning for leaks. An unresolved Medium-severity finding identifies that the private-repo leak rule can be bypassed by mentioning the gate name on the same line, which needs to be addressed before merge.

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

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Running ultrareview automatically — This adds a new CI security gate scanning untrusted PR/issue/comment bodies with regex-based policy and fail-closed paths, plus workflow event/concurrency changes — a subtle regex or workflow edge case could silently skip scans, leak internal names, or break merge gating.. I'll post findings when complete.

@qodo-code-review

qodo-code-review Bot commented Aug 6, 2026

Copy link
Copy Markdown

PR Summary by Qodo

CI: add issue/comment/PR body scanning to public-repo-guard

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

Grey Divider

AI Description

• Add a dedicated body-guard job to scan PR, issue, and comment text on edits.
• Keep the tree scan authoritative while preventing unstable check-runs via per-job concurrency.
• Vendor a body policy script plus fixture tests, with pinned PCRE2 ripgrep fallback.
Diagram

graph TD
  E{{"GitHub events"}} --> W["public-repo-guard workflow"] --> G["guard job (tree)"] --> GL["gitleaks scan"] --> CP["content-policy.sh"] --> T["body-policy fixtures"]
  W --> BG["body-guard job"] --> M["materialize body.txt"] --> BP["body-policy.sh"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Central reusable workflow (workflow_call) instead of vendoring scripts
  • ➕ Single source of truth for policy/workflow changes across repos
  • ➕ Simpler updates (one PR to the shared workflow)
  • ➖ Increases supply-chain/trust coupling to the caller workflow source
  • ➖ Harder to guarantee pinned, reviewable, repo-local policy artifacts at runtime (the PR explicitly wants deterministic vendoring)
2. Use pull_request_target for body scanning
  • ➕ Job code can always come from the trusted base branch tip
  • ➕ Avoids the "workflow file comes from PR head" limitation for forks
  • ➖ Easy to accidentally grant elevated permissions to fork PRs
  • ➖ Required-check semantics can be weakened by skipped/expected runs; PR already documents this risk
  • ➖ Still doesn’t solve that the tree scan must inspect PR content (so you still need pull_request)

Recommendation: Keep the PR’s approach: a separate body-guard job that checks out the trusted base ref and scans only materialized payload text, while leaving the existing tree scan on pull_request. This balances fork safety (no PR-controlled script execution), correct merge gating (required check remains meaningful), and operational practicality (fast body scans, no unnecessary gitleaks runs on every comment).

Files changed (3) +525 / -7

Enhancement (1) +172 / -0
body-policy.shIntroduce body leak policy for PR/issue/comment text +172/-0

Introduce body leak policy for PR/issue/comment text

• Adds a new policy script that scans materialized PR/issue/comment text for credential formats, internal markers, internal IPs, and operator paths while never echoing matched content. Implements explicit allowlisting via "guard:allow <reason>" plus an allowlist for discussions about the control, and a proximity-based private-repo rule keyed by GUARD_PRIVATE_REPOS to avoid blocking legitimate cross-repo references.

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

Tests (1) +144 / -0
body-policy.test.shAdd fixture tests for body-policy behavior and non-leaking output +144/-0

Add fixture tests for body-policy behavior and non-leaking output

• Adds hermetic fixture tests that validate both blocking and non-blocking cases, including regressions around quoting, case-insensitive matching, and multi-segment credential names. Verifies the policy never reprints matched text in logs/annotations and that scanner error paths fail closed with exit code 2.

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

Other (1) +209 / -7
public-repo-guard.ymlAdd body-guard job and strengthen tree guard semantics +209/-7

Add body-guard job and strengthen tree guard semantics

• Expands triggers to include issue and comment body changes, and adds a dedicated body-guard job that scans event payload text with trusted scripts from the base ref. Refactors concurrency to be job-scoped (tree cancels in-progress; body does not) and updates actions/checkout to a pinned v7.0.1 commit. Hardens ripgrep installation by requiring PCRE2 support with a pinned, checksum-verified fallback binary and adds a fixture self-test step for the body policy.

.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 (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Allowlist filter fails open ✓ Resolved 🐞 Bug ☼ Reliability
Description
In scripts/public-repo-guard/body-policy.sh, check() masks ripgrep failures in its post-processing
filters via || true, so an rg error (exit >=2) can be turned into an empty match set and
incorrectly treated as “no violations”. This contradicts the script’s stated fail-closed contract
and can cause the body gate to report PASS when the scanner is malfunctioning.
Code

scripts/public-repo-guard/body-policy.sh[R64-69]

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

●●● Strong

Fail-closed behavior matches guard contract; team previously accepted tightening allowlist/filter
logic in guard scripts.

PR-#7

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The script explicitly states that ripgrep errors must fail closed, but the later filter stages
suppress nonzero exit codes with || true, which includes real ripgrep errors (>=2). This can
convert a scanner failure into an empty match set and a false pass.

scripts/public-repo-guard/body-policy.sh[52-69]

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`’s `check()` function correctly fails closed when the *primary* `rg -nP` scan errors, but it then pipes the result through additional `rg` filters that end with `|| true`. With `set -o pipefail`, this suppresses *real* ripgrep errors (exit >=2) and can produce an empty `matches` value, incorrectly returning success.

### Issue Context
This script is part of a security gate; it explicitly documents that scanner errors must fail closed. The filter steps should treat exit code 1 (“no output after filtering”) as OK, but must treat exit code >=2 as a hard error.

### Fix Focus Areas
- scripts/public-repo-guard/body-policy.sh[52-69]

### Suggested fix
For each filtering pipeline:
1. Run the filter without `|| true`.
2. Capture `$?`.
3. If rc >= 2, emit an error and `exit 2`.
4. If rc is 0 or 1, proceed (rc==1 should just mean the filtered output is empty).

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


Grey Divider

Context
✅ Compliance rules (platform): 1 rule
Review mode: ⚖️ Balanced: Downgraded extended -> standard: change is below the extended eligibility bar (hunks 5/18, lines 532/200; both must reach the floor). Router rationale: This is a security-sensitive CI gate with substantial new workflow, shell-scanning, event/concurrency, trust-boundary, and regex logic across multiple independent paths, making redundant review materially valuable.

Grey Divider

Tip of the day
💡 Did you know, you can enable the Remediation agent and Qodo fixes findings in a dedicated fix PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@qodo-code-review

Copy link
Copy Markdown

Qodo Fixer

No findings are available for this PR yet. Findings appear here once Qodo has reviewed the PR.

devin-ai-integration[bot]

This comment was marked as resolved.

yakimoto and others added 2 commits August 6, 2026 17:30
…aundering

Address review findings:
- body-guard now checks out the gate scripts from the base branch tip
  (pull_request.base.sha), not the PR merge ref, so a fork PR can no longer
  rewrite body-policy.sh to pass its own body.
- The ABOUT_THE_CONTROL allowlist no longer applies to credential-format
  rules: a line naming the gate can still carry a live key. Only the explicit
  guard:allow marker exempts those. Fixture added.
- Preflight the ripgrep build for PCRE2 (script + both install steps) so a
  non-PCRE2 rg fails with the real cause instead of an opaque scanner error.

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

Address review findings:
- The private-repo-ops pattern opens with a global (?i) so repo names match
  case-insensitively, but that flag reached OPS_DETAIL and defeated its
  SCREAMING_CASE requirement: lowercase identifiers like api_key next to a
  repo name blocked clean PRs. The credential-name branch is now (?-i:...).
- Infra identifiers (Cloudflare account_id, Tailscale IP, operator path) now
  ignore the ABOUT_THE_CONTROL allowlist like the credential formats do: a
  real internal IP on a line naming the gate is still a leak.
- Fixtures for both.

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

This comment was marked as resolved.

…s, not 4)

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

This comment was marked as resolved.

yakimoto and others added 2 commits August 6, 2026 17:40
The trusted-ref checkout means the installing PR's base has no
body-policy.sh yet. That is exactly the pre-install state (no gate), and a
PR head cannot cause it, so skip with a visible warning instead of exiting
127; the gate is live from the first event after merge.

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

- issue_comment runs now scan just the new comment body. Re-scanning the
  parent issue's title/body meant one old violation failed every future
  comment, with line numbers into a concatenated buffer that maps to
  nothing. Each text is judged exactly once, on the event that changes it.
- An empty GUARD_PRIVATE_REPOS (fork runs may not receive org variables)
  now emits a visible warning instead of a quietly green check with the
  highest-value rule off.

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

This comment was marked as resolved.

…banners

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.

…ures

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>
@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_f411b32c-4210-4040-8d71-4f8e64ccb48b)

devin-ai-integration[bot]

This comment was marked as resolved.

… the required check

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

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_9a3fb931-0615-4088-a68b-9c131ab05f3e)

@yakimoto yakimoto closed this Aug 12, 2026
@yakimoto yakimoto reopened this Aug 12, 2026
@cursor

cursor Bot commented Aug 12, 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_7fc803d2-b187-43a5-9dc6-8d0d48742944)

@cursor cursor 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.

Risk: medium. Left a non-blocking comment — Cursor Bugbot and Cursor Security Agent were present but did not complete successfully (usage/spend limits), so this is not approved. Human review is needed; no additional assignable reviewers were available beyond the author.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

yakimoto and others added 2 commits August 12, 2026 14:07
…uard-body-scan

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
qodo-code-review[bot]

This comment was marked as resolved.

@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 75f4f7a

@qodo-code-review

Copy link
Copy Markdown

Qodo Fixer

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

Grey Divider

🔗 Fix PR: #54

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 (#54). It is NOT applied to this PR.
To use it: review Fix PR #54 (https://github.com/wave-av/api-spec/pull/54), 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 filter fails open

…t with || true

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 on lines +117 to +118
# v1.28.0 has no `version` subcommand; only the --version flag prints the version.
oasdiff --version

@devin-ai-integration devin-ai-integration Bot Aug 12, 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.

📝 Info: oasdiff flag change confirmed against the pinned binary

I fetched oasdiff v1.28.0 and checked both forms: oasdiff --version prints oasdiff version 1.28.0 (exit 0) while oasdiff version exits 100. The change is a genuine fix for a step that would otherwise fail the job.

Open in Devin Review

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

Comment thread scripts/public-repo-guard/body-policy.sh Outdated
Comment thread .github/workflows/public-repo-guard.yml
…ted checkout credentials

A body is unreviewed free text: any author or commenter can type
guard:allow, so for the credential-format rules the marker was a
one-token bypass of the whole gate. Those rules are now never-exempt
(no guard:allow, no about-allowlist); infra-identifier rules keep
guard:allow as the honest, visible way to carry a live-shaped example.
Regression fixtures added for both tiers (33 pass).

Both checkouts in the guard workflow now set persist-credentials: false,
matching foundation-gate.yml — no step needs git credentials, and the
tree job executes PR-controlled scripts.

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

This comment was marked as resolved.

…ainst URL paths

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 4 new potential issues.

Open in Devin Review

Comment thread scripts/public-repo-guard/body-policy.sh Outdated
Comment thread .github/workflows/public-repo-guard.yml
Comment on lines +285 to +288
if [ -z "${GUARD_PRIVATE_REPOS:-}" ]; then
echo "::error title=public-repo-guard (body-guard)::GUARD_PRIVATE_REPOS is empty for this run, so the private-repo proximity rule would be silently OFF. Refusing to report a green body gate without it. Configure the org/repo variable; for fork PRs a maintainer must verify the body."
exit 1
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Body gate hard-fails when the org variable is not delivered, e.g. on fork PRs

The fail-closed check turns a missing/empty GUARD_PRIVATE_REPOS into a red required check rather than a warning. The comment acknowledges the fork case, but the practical consequence is that if configuration variables are not handed to fork-triggered pull_request runs in this org, every external contribution will show a permanently failing "Body content policy" check that the contributor cannot fix. Worth confirming against a real fork PR before making this check required.

Open in Devin Review

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

Comment thread scripts/public-repo-guard/body-policy.sh Outdated
…n; add changelog entry

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 +178 to +189
# Known limit, considered and accepted: on pull_request the workflow FILE
# itself comes from the PR head, so this trusted-ref design holds only for
# PRs that do not edit this workflow. That edit is loudly visible in the
# PR's own diff, and the same move neuters the REQUIRED tree check too
# (which must run PR content, so pull_request_target cannot protect it) —
# the class is closed org-side, by requiring review on workflow changes,
# not by a per-job trigger swap. Swapping this job to pull_request_target
# would even WEAKEN the gate: its run would attach a skipped
# "Secrets + content policy" check to the head SHA, and a skipped
# required check satisfies branch protection — a workflow-deleting PR,
# unmergeable today ("Expected — waiting"), would become mergeable.
ref: ${{ github.event.pull_request.base.sha || github.ref }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟨 Body gate can be neutralized by a quoted marker or a PR that edits the workflow

The body gate's checkout pins to the trusted base ref for the scripts (.github/workflows/public-repo-guard.yml:189), but the workflow file itself on a pull_request event comes from the PR head, so a PR that edits this workflow chooses its own body gate. Additionally the internal-marker rule exempts any marker wrapped in straight/smart/backtick quotes (scripts/public-repo-guard/body-policy.sh:155), which is a one-character bypass. Both are explicitly documented and accepted in-file as trade-offs against false positives, so this is noted as hardening context rather than an unacknowledged hole.

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.

The comment itself classifies both points as documented, accepted trade-offs ("hardening context rather than an unacknowledged hole"): the workflow-edit limit is mitigated org-side via required review on workflow changes and a pull_request_target swap would weaken the gate, and the quoted-marker exemption is a deliberate use-vs-mention design with guard:allow as the honest bypass path.

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.

1 participant