Context
src/selfhost/blob-store.ts:32-43's pathFor(key) throws "blob key escapes base dir" as defense-in-depth against path traversal. get() (lines 16-29) calls pathFor(key) inside a blanket try { } catch { return null; }, so a traversal attempt is indistinguishable from an ordinary cache miss — no log, no metric. put()/delete() call pathFor(key) unguarded, so the same check throws visibly there. get() is the path most likely to be probed (reads, via the /loopover/shot serve route), and it's exactly the one where this defense-in-depth failure goes invisible.
Requirements
- Change
get() to distinguish a genuine "file not found" outcome from a pathFor traversal-check failure — log/record the traversal-check failure distinctly (matching whatever logging convention this file's sibling error paths use) before returning null, rather than swallowing it silently.
- Do not weaken the traversal check itself, and do not change
put()/delete()'s already-correct unguarded behavior.
Test Coverage Requirements
99%+ Codecov patch coverage; a regression test confirming a traversal-attempting key logs/records the attempt distinctly from a genuine cache miss.
Deliverables
Expected Outcome
A path-traversal probe against the blob store's read path is visible in logs/metrics instead of silently looking like a normal cache miss.
Links & Resources
src/selfhost/blob-store.ts:16-43
Context
src/selfhost/blob-store.ts:32-43'spathFor(key)throws"blob key escapes base dir"as defense-in-depth against path traversal.get()(lines 16-29) callspathFor(key)inside a blankettry { } catch { return null; }, so a traversal attempt is indistinguishable from an ordinary cache miss — no log, no metric.put()/delete()callpathFor(key)unguarded, so the same check throws visibly there.get()is the path most likely to be probed (reads, via the/loopover/shotserve route), and it's exactly the one where this defense-in-depth failure goes invisible.Requirements
get()to distinguish a genuine "file not found" outcome from apathFortraversal-check failure — log/record the traversal-check failure distinctly (matching whatever logging convention this file's sibling error paths use) before returningnull, rather than swallowing it silently.put()/delete()'s already-correct unguarded behavior.Test Coverage Requirements
99%+ Codecov patch coverage; a regression test confirming a traversal-attempting key logs/records the attempt distinctly from a genuine cache miss.
Deliverables
get()distinguishes and logs a traversal-check failure from an ordinary miss.Expected Outcome
A path-traversal probe against the blob store's read path is visible in logs/metrics instead of silently looking like a normal cache miss.
Links & Resources
src/selfhost/blob-store.ts:16-43