Skip to content

fix(repo-health): decode Git-quoted leakage paths - #2101

Merged
bradygaster merged 2 commits into
devfrom
bradygaster-issue-1800-repo-health-path-decoding
Sep 28, 2026
Merged

bradygaster merged 2 commits into
devfrom
bradygaster-issue-1800-repo-health-path-decoding

Conversation

@bradygaster

Copy link
Copy Markdown
Collaborator

Summary

  • decode Git --name-only C-quoted paths byte-first into exact raw UTF-8 before scanner JSON and comment transport
  • fail closed on malformed quoting, escapes, octal, UTF-8, unsupported paths, scanner failures, and invalid reporter output
  • preserve the base-controlled pull_request_target trust boundary; PR-head code remains confined to the read-only shadow workflow
  • require exact first-line reporter markers to prevent cross-job marker injection from hostile filenames
  • update the authoritative canary assertion to compare the exact raw semantic path

Working as agentic-workflows-dev (Agentic Workflows Engineer).

Closes #1800

Validation

  • npx --no-install vitest run test/scripts/check-squad-leakage.test.ts test/scripts/repo-health-comment-transport.test.ts — 49 tests passed
  • npx --no-install eslint scripts/check-squad-leakage.mjs scripts/git-path-decoder.mjs scripts/repo-health-comment.mjs test/scripts/check-squad-leakage.test.ts test/scripts/repo-health-comment-transport.test.ts — passed
  • actionlint .github/workflows/squad-repo-health.yml .github/workflows/squad-repo-health-shadow.yml — passed
  • clean and invalid-base invocations of scripts/check-squad-leakage.mjs — clean JSON and fail-closed behavior verified
  • CI=true npm run build — passed for SDK and CLI
  • real temporary Git repositories verified the exact canary path under core.quotePath=true and false
  • real scanner stdout passed through the real production workflow github-script body and reporter fake-Octokit contract
  • trust-boundary tests confirm the authoritative workflow stays base-controlled and the shadow workflow stays read-only/non-authoritative
  • gh-aw validation not applicable: these are ordinary GitHub Actions workflows, not gh-aw source/lock artifacts

Security review

Focused final-diff security review initially found cross-job marker injection through substring comment ownership. The revision now requires the managed marker as the exact first line and includes a regression test. Focused rereview verdict: APPROVE — no security vulnerabilities found.

No dependencies were added. The existing pull_request_target workflow never checks out or executes PR-head code.

Post-merge authoritative canary

After this reaches dev, follow .github/REPO_HEALTH_RUNBOOK.md to:

  1. open a disposable PR containing exactly .squad/canary-paired-${-apostrophe-'-"double quote".md
  2. require one authoritative leakage marker whose list entry equals the exact raw semantic path
  3. remove the file, push, and require stale marker deletion
  4. record the disposable PR and both successful Repo Health run URLs on Runbook gotcha: any fix to squad-repo-health.yml is unverifiable in CI until it merges #1800, then close/delete the canary branch without merging

Closes #1800

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings September 28, 2026 23:31
@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

🛫 PR Readiness Check

ℹ️ This comment updates on each push. Last checked: commit ddd948b

PR Scope: 🔧 Infrastructure

⚠️ 3 item(s) to address before review

Status Check Details
❌ Single commit 2 commits — consider squashing before review
✅ Not in draft Ready for review
✅ Branch up to date Up to date with dev
❌ Copilot review No Copilot review yet — it may still be processing
✅ Changeset present No source files changed — changeset not required
✅ Scope clean No .squad/ or docs/proposals/ files
✅ No merge conflicts No merge conflicts
❌ Copilot threads resolved 3 unresolved Copilot thread(s) — fix and resolve before merging
✅ CI passing All checks passing

Files Changed (8 files, +382 −39)

File +/−
.github/REPO_HEALTH_RUNBOOK.md +4 −1
.github/workflows/squad-repo-health-shadow.yml +2 −0
.github/workflows/squad-repo-health.yml +1 −1
scripts/check-squad-leakage.mjs +25 −27
scripts/git-path-decoder.mjs +102 −0
scripts/repo-health-comment.mjs +20 −7
test/scripts/check-squad-leakage.test.ts +124 −0
test/scripts/repo-health-comment-transport.test.ts +104 −3

Total: +382 −39


This check runs automatically on every push. Fix any ❌ items and push again.
See CONTRIBUTING.md and PR Requirements for details.

@github-actions

Copy link
Copy Markdown
Contributor

🟡 Impact Analysis — PR #2101

Risk tier: 🟡 MEDIUM

📊 Summary

Metric Count
Files changed 8
Files added 2
Files modified 6
Files deleted 0
Modules touched 3

🎯 Risk Factors

  • 8 files changed (6-20 → MEDIUM)
  • 3 modules touched (2-4 → MEDIUM)

📦 Modules Affected

ci-workflows (3 files)
  • .github/REPO_HEALTH_RUNBOOK.md
  • .github/workflows/squad-repo-health-shadow.yml
  • .github/workflows/squad-repo-health.yml
scripts (3 files)
  • scripts/check-squad-leakage.mjs
  • scripts/git-path-decoder.mjs
  • scripts/repo-health-comment.mjs
tests (2 files)
  • test/scripts/check-squad-leakage.test.ts
  • test/scripts/repo-health-comment-transport.test.ts

This report is generated automatically for every PR. See #733 for details.

@github-actions

Copy link
Copy Markdown
Contributor

🏗️ Architectural Review

Authoritative evidence: base-controlled pull_request_target reporter.

⚠️ Architectural review: 1 info.

Severity Category Finding Files
ℹ️ info template-sync Template files changed in .github/workflows/ but not in other template locations. If these templates should stay in sync, consider updating the others too. Changed: .github/workflows/, Unchanged: templates/, .squad-templates/, packages/squad-cli/templates/

Automated architectural review — informational only.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Out-of-range octal escapes are silently transformed, and several malformed-output tests can pass through the mocked deletion failure.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity · 1 Low severity

Open (3)
What changed in this PR

Hardens the repo-health leakage pipeline by decoding Git-quoted paths exactly and validating scanner/comment transport.

Changes:

  • Adds strict byte-first Git path decoding and scanner validation.
  • Strengthens reporter ownership and malformed-output handling.
  • Adds integration tests, shadow coverage, and canary verification.
File Description
scripts/​git-path-decoder.mjs Adds Git path decoding and validation.
scripts/​check-squad-leakage.mjs Uses decoder and fails closed.
scripts/​repo-health-comment.mjs Validates output and exact markers.
.github/​workflows/​squad-repo-health.yml Separates scanner JSON from diagnostics.
.github/​workflows/​squad-repo-health-shadow.yml Expands shadow workflow coverage.
.github/​REPO_HEALTH_RUNBOOK.md Verifies the exact canary path.
test/​scripts/​check-squad-leakage.test.ts Tests decoding and scanner behavior.
test/​scripts/​repo-health-comment-transport.test.ts Tests workflow/report transport.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +57 to +65
if (/[0-7]/.test(escaped)) {
const octal = `${escaped}${inner[index + 1] ?? ''}${inner[index + 2] ?? ''}`;
if (!/^[0-7]{3}$/.test(octal)) {
throw new Error('incomplete octal escape in Git C-quoted path');
}
bytes.push(Number.parseInt(octal, 8));
index += 2;
continue;
}
Comment on lines +384 to +388
await expect(runWorkflowScript(
step,
{ 'steps.leakage.outputs.result': output },
{ comments: [{ id: 42, body: `${marker}\nold` }], fail: 'deleteComment' },
)).rejects.toThrow();
Comment on lines +50 to +53
} catch (err) {
const errorMessage = err instanceof Error ? err.message : String(err);
console.error(`Squad leakage scan failed: ${errorMessage}`);
process.exitCode = 1;
@bradygaster
bradygaster merged commit 09042a7 into dev Sep 28, 2026
19 checks passed
@bradygaster
bradygaster deleted the bradygaster-issue-1800-repo-health-path-decoding branch October 3, 2026 00:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Runbook gotcha: any fix to squad-repo-health.yml is unverifiable in CI until it merges

2 participants