Skip to content

fix(miner): reject path-traversal repo segments in 4 remaining normalizeRepoFullName parsers - #8058

Closed
lourincedaging0-commits wants to merge 1 commit into
JSONbored:mainfrom
lourincedaging0-commits:fix/repo-segment-guard-4-miner-parsers-7795
Closed

fix(miner): reject path-traversal repo segments in 4 remaining normalizeRepoFullName parsers#8058
lourincedaging0-commits wants to merge 1 commit into
JSONbored:mainfrom
lourincedaging0-commits:fix/repo-segment-guard-4-miner-parsers-7795

Conversation

@lourincedaging0-commits

Copy link
Copy Markdown
Contributor

Summary

normalizeRepoFullName in contribution-profile-cache.ts, prediction-ledger.ts, replay-snapshot.ts and run-state.ts only validated "exactly one slash, both halves non-empty" — so a ./../control-char owner or repo segment (owner/.., ../repo, a tab/newline inside a segment) passed through and was persisted as a SQLite key and echoed back through the sibling CLIs.

#5831 and #7525 already extended isValidRepoSegment (from repo-clone.ts) to the other ten normalizeRepoFullName siblings for exactly this "persisted into SQLite" reason; these four were never touched.

Changes

  • Import and call isValidRepoSegment on both owner and repo in all four parsers, matching the exact call shape used by the already-fixed siblings (claim-ledger.ts, governor-state.ts, portfolio-queue.ts, worktree-allocator.ts). No new validation mechanism.
  • Per-store regression test covering a ./../control-char segment, mirroring miner-claim-ledger.test.ts's existing ../etc assertion.

Verification

All four affected test suites pass locally (81 tests), including the new path-traversal assertions.

Closes #7795

…izeRepoFullName parsers

contribution-profile-cache.ts, prediction-ledger.ts, replay-snapshot.ts and
run-state.ts each defined normalizeRepoFullName but only checked "one slash,
both halves non-empty" — a `.`/`..`/control-char owner or repo segment (e.g.
"owner/..", "../repo", tab/newline in a segment) passed through and was
persisted as a SQLite key / echoed back through the sibling CLIs.

JSONbored#5831 and JSONbored#7525 already rolled isValidRepoSegment out to the other ten
normalizeRepoFullName siblings for exactly this reason; these four were missed.
Import and call isValidRepoSegment on both segments, matching the established
pattern (claim-ledger.ts, governor-state.ts, portfolio-queue.ts, ...). Add a
per-store regression test covering a `.`/`..`/control-char segment.

Closes JSONbored#7795
@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 22, 2026
@loopover-orb

loopover-orb Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Caution

🛑 LoopOver review result - reject/close recommended

Review updated: 2026-07-22 17:24:03 UTC

8 files · 1 AI reviewer · 1 blocker · CI green · unknown

🛑 Suggested Action - Reject/Close

Review summary
This PR closes out issue #7795 by applying the same `isValidRepoSegment` guard (from `repo-clone.ts`) to the four remaining `normalizeRepoFullName` parsers that #5831/#7525 missed, matching the exact call shape used in the ten already-fixed siblings. Each parser gets one line added right after the existing slash/empty-segment check, and each has a corresponding regression test asserting `.`/`..`/control-char segments now throw `invalid_repo_full_name`. The change is narrow, mechanical, and consistent across all four files with no behavioral surprises — the fix is correctly placed at the same normalization layer as its siblings.

Nits — 5 non-blocking
  • The `replay-snapshot.ts` file already has its own `normalizeCommitSha` traversal guard for commit SHAs (per its inline comments referencing replay-snapshot.ts's normalizeCommitSha has no format validation, letting a crafted value escape the intended snapshot directory via path.join #7796) — worth confirming in review that this owner/repo guard doesn't overlap/conflict with that existing SHA-specific validation, though from the diff they guard different fields so this is just a note, not an issue.
  • Each of the four files repeats the identical `if (!isValidRepoSegment(owner) || !isValidRepoSegment(repo)) throw new Error("invalid_repo_full_name");` line — consistent with the ten existing siblings' pattern per the description, so no action needed, but a shared helper (e.g. `normalizeOwnerRepoSegments`) could reduce this duplication across all 14 call sites if a future PR wants to unify it.
  • Consider, in a follow-up, extracting the common `[owner, repo, extra] = ...split("/")` + `isValidRepoSegment` checks used across all 14 `normalizeRepoFullName` implementations into one shared utility to eliminate the copy-pasted validation logic, per DRY, though this PR correctly scopes itself to matching the existing per-file pattern rather than a refactor.
  • Pull request duplicates other open work — Check for an existing pull request or issue covering this change and coordinate or consolidate before continuing.
  • 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

📋 Copy for AI agents — paste into your coding agent
Fix the following blocker(s) from this PR review:

1. Linked issue overlaps another open PR: Other open pull requests reference the same linked issue set: #7999. — Review the related PRs before spending reviewer time on duplicate work.

Decision drivers

  • ❌ Code review — 1 blocker (1 reviewer)
  • ❌ Gate result — Blocking (Repo-configured hard blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #7795
Related work ⚠️ Same linked issue: #7999 Another open PR references the same linked issue.
Change scope ❌ 8/20 High review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 81 registered-repo PR(s), 33 merged, 5 issue(s).
Contributor context ✅ Confirmed Gittensor contributor lourincedaging0-commits; Gittensor profile; 81 PR(s), 5 issue(s).
Improvement ✅ Minor risk: low · value: minor · LLM: moderate
Linked issue satisfaction

Addressed
All four target files (contribution-profile-cache.ts, prediction-ledger.ts, replay-snapshot.ts, run-state.ts) now import and call isValidRepoSegment on both owner and repo, matching the exact pattern used by the ten already-fixed siblings, and each has a corresponding regression test asserting rejection of '..'/'.'/control-char segments.

Review context
Contributor next steps
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.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask <question> answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat <question> answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

🟩 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 LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@loopover-orb

loopover-orb Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

LoopOver is closing this pull request on the maintainer's behalf (Linked issue overlaps another open PR; duplicate of open PR #7999). 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 22, 2026
@codecov

codecov Bot commented Jul 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 25.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 38.18%. Comparing base (8329069) to head (ee2e29d).
⚠️ Report is 20 commits behind head on main.

Files with missing lines Patch % Lines
...s/loopover-miner/lib/contribution-profile-cache.ts 0.00% 1 Missing ⚠️
packages/loopover-miner/lib/prediction-ledger.ts 0.00% 1 Missing ⚠️
packages/loopover-miner/lib/run-state.ts 0.00% 1 Missing ⚠️

❌ Your patch status has failed because the patch coverage (25.00%) 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    #8058       +/-   ##
===========================================
- Coverage   91.93%   38.18%   -53.76%     
===========================================
  Files         742        4      -738     
  Lines       76035      275    -75760     
  Branches    23079       59    -23020     
===========================================
- Hits        69904      105    -69799     
+ Misses       5037      170     -4867     
+ Partials     1094        0     -1094     
Flag Coverage Δ
control-plane ?
rees ?
shard-1 38.18% <25.00%> (-20.91%) ⬇️
shard-2 0.00% <0.00%> (-48.44%) ⬇️
shard-3 0.00% <0.00%> (-54.59%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
packages/loopover-miner/lib/replay-snapshot.ts 100.00% <100.00%> (ø)
...s/loopover-miner/lib/contribution-profile-cache.ts 0.00% <0.00%> (-100.00%) ⬇️
packages/loopover-miner/lib/prediction-ledger.ts 0.00% <0.00%> (-80.60%) ⬇️
packages/loopover-miner/lib/run-state.ts 0.00% <0.00%> (-100.00%) ⬇️

... and 738 files with indirect coverage changes

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.

4 sibling normalizeRepoFullName parsers still skip the path-safety guard #5831/#7525 already added to every other sibling

1 participant