Skip to content

Commit fe67f9d

Browse files
committed
fix(miner): validate commitSha as 7-40 hex before joining it into the replay path
normalizeCommitSha accepted any non-empty string and the value was join()'d straight into planReplaySnapshotPath's on-disk path, so a '../..'-laden commitSha could escape the repo dir (path traversal). Enforce the same 7-40 hex format its sibling replay-task-generation.ts already applies, so a malformed/traversal value throws invalid_commit_sha before it ever reaches path.join. Placeholder short SHAs in the affected fixtures (miner-replay-snapshot + the miner-store-seam-rollout cross-file consumer) updated to valid hex. Closes #7796
1 parent 510d25b commit fe67f9d

3 files changed

Lines changed: 80 additions & 56 deletions

File tree

packages/loopover-miner/lib/replay-snapshot.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,12 @@ function normalizeRepoFullName(repoFullName: string): string {
7777

7878
function normalizeCommitSha(commitSha: string): string {
7979
if (typeof commitSha !== "string" || !commitSha.trim()) throw new Error("invalid_commit_sha");
80-
return commitSha.trim();
80+
const trimmed = commitSha.trim();
81+
// A commit SHA is 7-40 hex chars; reject anything else (#7796) so an unvalidated value — e.g. a `../../..`
82+
// traversal sequence — can never be join()'d into planReplaySnapshotPath's on-disk path and escape the repo.
83+
// Mirrors the format check replay-task-generation.ts already applies (`/^[0-9a-f]{7,40}$/i`).
84+
if (!/^[0-9a-f]{7,40}$/i.test(trimmed)) throw new Error("invalid_commit_sha");
85+
return trimmed;
8186
}
8287

8388
/** Worktree exports live under this dir inside the repo, mirroring worktree-allocator.ts's WORKTREE_SUBDIR. */

0 commit comments

Comments
 (0)