Skip to content

fix(review): scan patch-less PR files for leaked secrets - #3464

Closed
RealDiligent wants to merge 1 commit into
JSONbored:mainfrom
RealDiligent:fix/secret-scan-patchless-files-v2
Closed

fix(review): scan patch-less PR files for leaked secrets#3464
RealDiligent wants to merge 1 commit into
JSONbored:mainfrom
RealDiligent:fix/secret-scan-patchless-files-v2

Conversation

@RealDiligent

Copy link
Copy Markdown
Contributor

Problem

The unconditional secret_leak hard blocker scans only + lines from buildSecretScanDiff. GitHub omits inline patch for binary/large changed files (>~1 MB), so those files produced header-only entries with no scannable body. A PR could commit a concrete credential in a patch-less file and pass the gate.

Fix

  • Extract patch-less enrichment into src/queue/patchless-secret-scan.ts with dedicated unit tests (100% line coverage).
  • When headSha is available at gate time, fetch head/base content via Contents API and synthesize scannable + lines for patch-less added/modified/renamed files.
  • Fail closed when content exceeds the 512KB cap or cannot be fetched completely.

Test plan

  • npm run typecheck
  • test/unit/patchless-secret-scan.test.ts (41 tests)
  • test/unit/safety-wiring.test.ts (unchanged, passes)
  • CI codecov/patch >= 99%

)

Extract patch-less secret-scan enrichment into patchless-secret-scan.ts with
full unit coverage. When GitHub omits inline diff for binary/large files,
fetch head/base content via Contents API and synthesize scannable + lines
before the unconditional secret_leak hard blocker runs.

Co-authored-by: Cursor <cursoragent@cursor.com>
@RealDiligent
RealDiligent requested a review from JSONbored as a code owner July 5, 2026 08:12
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 5, 2026
@loopover-orb

loopover-orb Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Caution

🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥

🛑 Gittensory review result - reject/close recommended

Review updated: 2026-07-05 08:13:31 UTC

3 files · 1 AI reviewer · 3 blockers · readiness 73/100 · CI pending · blocked

🛑 Suggested Action - Reject/Close

  • No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.
  • Maintainer requires a linked issue — Link the relevant issue (for example Closes #123) before opening the PR.
  • AI reviewers agree on a likely critical defect: src/queue/patchless-secret-scan.ts:123 passes `SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS` to `getFileContent`, so a fetcher that honors `maxChars` can return a 512000-character truncated prefix and make `isOverSecretScanContentLimit` unable to fail closed for an oversized head file
  • request `SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS + 1` for head/base reads and then keep the existing `> SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS` check, e.g. `const readLimit = SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS + 1
  • const headContent = await args.fetcher.getFileContent(file.path, headSha, readLimit)
  • `. — Resolve the flagged defect, or override if the AI reviewers are mistaken, then re-run the gate.

Review summary
The change correctly moves the deterministic secret scan beyond GitHub's inline patch field by synthesizing scannable additions for patch-less files and wiring an incomplete-scan finding into the gate. The main wiring is coherent, but the oversize fail-closed path is implemented at the wrong layer: the production fetch call asks for exactly the cap, so a cap-respecting fetcher can truncate an oversized file to 512KB and make the later `> cap` check unreachable. The tests cover oversize by returning a fabricated 512001-character string from the mock instead of exercising the real cap contract.

Blockers

  • src/queue/patchless-secret-scan.ts:123 passes `SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS` to `getFileContent`, so a fetcher that honors `maxChars` can return a 512000-character truncated prefix and make `isOverSecretScanContentLimit` unable to fail closed for an oversized head file; request `SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS + 1` for head/base reads and then keep the existing `> SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS` check, e.g. `const readLimit = SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS + 1; const headContent = await args.fetcher.getFileContent(file.path, headSha, readLimit);`.
  • src/queue/patchless-secret-scan.ts:143 and src/queue/patchless-secret-scan.ts:154 repeat the same cap-detection bug for base content, so an oversized base for modified/renamed files can be silently truncated and diffed instead of producing the incomplete hard finding; use the same `SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS + 1` read limit for both base fetches.
Nits — 6 non-blocking
  • test/unit/patchless-secret-scan.test.ts should add a production-contract test where the mock fetcher returns exactly the requested `maxChars` characters for an oversized source, because the current oversize tests fabricate a return value longer than the requested cap and miss the reachable truncation bug.
  • src/queue/processors.ts:6696 checks raw `args.headSha` before constructing the fetcher while `enrichSecretScanFilesWithPatchFallback` trims it later, so whitespace-only SHAs still pay the fetcher setup cost before no-oping; trim once before the wiring branch for consistency.
  • In src/queue/patchless-secret-scan.ts, define a local `const fetchLimit = SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS + 1` and pass that to every `getFileContent` call so the cap check can observe oversize content.
  • In test/unit/patchless-secret-scan.test.ts, make the oversize fetcher assert the received `maxChars` and return `'x'.repeat(maxChars ?? 0)` to prove the code fails closed when the backend only returns the requested sentinel byte.
  • In src/queue/processors.ts, gate fallback setup on `const headSha = args.headSha?.trim()` and pass that through to avoid divergent blank-SHA behavior.
  • Readiness score is below the configured threshold — Use the readiness panel as advisory maintainer context; the score does not block this PR.

Why this is blocked

  • src/queue/patchless-secret-scan.ts:123 passes `SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS` to `getFileContent`, so a fetcher that honors `maxChars` can return a 512000-character truncated prefix and make `isOverSecretScanContentLimit` unable to fail closed for an oversized head file; request `SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS + 1` for head/base reads and then keep the existing `> SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS` check, e.g. `const readLimit = SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS + 1; const headContent = await args.fetcher.getFileContent(file.path, headSha, readLimit);`.
  • No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.
  • Maintainer requires a linked issue — Link the relevant issue (for example Closes #123) before opening the PR.
Signal Result Evidence
Code review ❌ 3 blockers 1 reviewer
Linked issue ⚠️ Missing No linked issue or no-issue rationale found.
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (no linked issue context).
Validation posture ❌ 5/25 Preflight is holding this PR: the review lane is unavailable, so it is not ready for automated review.
Contributor workload ✅ 10/10 Author activity: 138 registered-repo PR(s), 18 merged, 0 issue(s).
Contributor context ✅ Confirmed Gittensor contributor RealDiligent; Gittensor profile; 138 PR(s), 0 issue(s).
Gate result ❌ Blocking Repo-configured hard blocker found.
Review context
  • Author: RealDiligent
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository registration is not available in the local Gittensory cache.
  • Public profile languages: Ruby, Svelte, TypeScript, Cuda, JavaScript, Markdown
  • Official Gittensor activity: 138 PR(s), 0 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Explain no-issue PR.
  • Await review-lane availability.
  • Refresh registry data or choose a registered active repo.
  • Link the issue being solved, or explicitly explain why this is a no-issue PR.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@loopover-orb

loopover-orb Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Gittensory is closing this pull request on the maintainer's behalf (No linked issue detected; Maintainer requires a linked issue; AI reviewers agree on a likely critical defect: src/queue/patchless-secret-scan.ts:123 passes `SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS` to `getFileContent`, so a fetcher that honors `maxChars` can return a 512000-character truncated prefix and make `isOverSecretScanContentLimit` unable to fail closed for an oversized head file; request `SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS + 1` for head/base reads and then keep the existing `> SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS` check, e.g. `const readLimit = SECRET_SCAN_PATCH_FALLBACK_MAX_CHARS + 1; const headContent = await args.fetcher.getFileContent(file.path, headSha, readLimit);`.). This is an automated maintenance action — to pursue this change, please open a new pull request with the issues resolved. Closed PRs may be analyzed later to improve review accuracy, but they are not automatically reopened or re-reviewed.

@loopover-orb loopover-orb Bot closed this Jul 5, 2026
@codecov

codecov Bot commented Jul 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.73418% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 93.02%. Comparing base (4de33af) to head (d093015).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/queue/patchless-secret-scan.ts 98.52% 0 Missing and 1 partial ⚠️

❌ Your patch status has failed because the patch coverage (98.73%) is below the target coverage (99.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3464      +/-   ##
==========================================
+ Coverage   93.01%   93.02%   +0.01%     
==========================================
  Files         297      298       +1     
  Lines       31013    31091      +78     
  Branches    11310    11338      +28     
==========================================
+ Hits        28846    28923      +77     
  Misses       1512     1512              
- Partials      655      656       +1     
Files with missing lines Coverage Δ
src/queue/processors.ts 93.12% <100.00%> (+0.02%) ⬆️
src/queue/patchless-secret-scan.ts 98.52% <98.52%> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

RealDiligent added a commit to RealDiligent/gittensory that referenced this pull request Jul 5, 2026
loopover-orb Bot pushed a commit that referenced this pull request Jul 5, 2026
…#3493)

* fix(review): scan patch-less PR files for leaked secrets (#2821)

Extract patch-less secret-scan enrichment into patchless-secret-scan.ts with
full unit coverage. When GitHub omits inline diff for binary/large files,
fetch head/base content via Contents API and synthesize scannable + lines
before the unconditional secret_leak hard blocker runs.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(review): cover default-status branch for patch-less secret scan (#3464)

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(review): use +1 fetch probe for patch-less secret scan cap (#3481)

The grounding FileFetcher returns maxChars+1 when content exceeds the cap;
pass SECRET_SCAN_FETCH_PROBE_CHARS so oversized files fail closed instead of
scanning a truncated prefix.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(review): precheck patch-less fetch and cap incomplete-path detail

Skip makeGithubFileFetcher when every file already has inline patch.
Cap fail-closed advisory path list (title keeps full count).

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant