fix(rees): harden SLUG_RE against dot-segment path traversal in 17 analyzers - #4959
Conversation
…alyzers Change SLUG_RE from the weak /^[A-Za-z0-9._-]+$/ to /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/ in all 17 review-enrichment analyzers still using the old pattern, matching duplication-delta.ts and codeowners.ts (the only two files already hardened). A bare [A-Za-z0-9._-]+ class lets a slug segment made entirely of dots (e.g. owner="..") pass validation, since every character in ".." is individually allowed. These owner/repo values get spliced into GitHub Contents-API URLs passed to fetch()/new URL(); a leading-dot segment could let a URL parser's dot-segment resolution rewrite the path, sending the auth token somewhere other than the intended owner/repo. Requiring an alphanumeric first character closes that gap without any behavior change for a legitimate slug (GitHub owner/repo names always start with an alphanumeric character). Each changed analyzer gets a test confirming a ".."-shaped owner/repo segment is rejected (fails safe, no finding, never throws) — extending an existing invalid-slug test where one already existed, adding a new one otherwise. Also normalizes three test files (exhaustiveness-drift, flaky-test, unused-export) from pre-existing mixed CRLF/LF line endings to plain LF, matching every other file in the package; the mixed endings were already present on main and were tripping git diff --check on these files now that they're touched.
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ Gittensory review result - approve/merge recommendedReview updated: 2026-07-11 03:22:12 UTC
✅ Suggested Action - Approve/Merge
Review summary Nits — 4 non-blocking
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🟩 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.
|
Summary
SLUG_REin 17 review-enrichment analyzers from the weak/^[A-Za-z0-9._-]+$/to/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/, matching the two analyzers (duplication-delta.ts,codeowners.ts) that already use the stricter pattern.[A-Za-z0-9._-]+class lets a slug segment made entirely of dots (e.g.owner="..") pass validation, since every character in".."is individually allowed by that class. These owner/repo values get spliced into a GitHub Contents-API URL passed tofetch()/new URL(); a leading-dot segment could let a URL parser's dot-segment resolution rewrite the path, sending the request (and the real auth token) somewhere other than the intendedowner/repo. Requiring an alphanumeric first character closes that gap with no behavior change for any legitimate slug.".."-shaped owner/repo segment is now rejected (fails safe, no finding, never throws) — extending an existing invalid-slug test where one already existed, adding a new one otherwise.exhaustiveness-drift.test.ts,flaky-test.test.ts,unused-export.test.ts) from pre-existing mixed CRLF/LF line endings (already present onmain, unrelated to this change) to plain LF, matching every other file in the package — the mixed endings were trippinggit diff --checkonce these files were touched for this PR.Closes #4955
Scope
type(scope): short summaryConventional Commit format.review-enrichment/src/analyzers/**and its tests only — no backend/UI/MCP/docs/dependency/deploy changes mixed in.CONTRIBUTING.mdand does not touch GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run actionlintnpm run typechecknpm run test:coverage— passes (13910 tests, coverage thresholds met); note none of the 17 changed analyzer/test files are in vitest's coverageincludescope (only the untouchedreview-enrichment/src/analyzers/codeowners.tsis), socodecov/patchhas no lines to grade on this diff. REES's own gate,npm run rees:test, is the relevant bar here and is fully green (1308/1308, including all 17 new dot-segment tests).npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:lintnpm run ui:typechecknpm run ui:buildnpm audit --audit-level=moderate— 0 vulnerabilitiesSafety
UI Evidence
Not applicable — this PR only touches
review-enrichment/src/analyzers/**andreview-enrichment/test/**, a backend service package with no UI surface.Notes
// rejects \..` and other path-traversal segments) already used bycodeowners.ts`, kept byte-identical across all 17 files for consistency rather than 17 different phrasings.churn-hotspot.ts,coverage-delta.ts,flaky-test.ts,revert-recurrence.ts) guard with!owner || !repo || !SLUG_RE.test(owner) || !SLUG_RE.test(repo)but without an explicitparts.length !== 2check that the other 13 files have. That's a separate, pre-existing gap unrelated to the dot-segment character-class issue this PR fixes (a 3+ segmentrepoFullNamestill resolves to the correct first two parts; it isn't a path-traversal risk), so it's left out of this mechanical, single-purpose pass — flagging it here as a possible small follow-up rather than silently leaving it unmentioned.