build: On current obsidian-connor main, re-cut the relPath() hardening: reject any path whose segments begin with… #15
Loading…
Reference in a new issue
No description provided.
Delete branch "build/bdcb3dfb"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What changed
build/bdcb3dfb→main— 3 file(s), +82/−9.src/lib/paths.tssrc/main.tstest/paths.test.tsWhy
Done — the gate is green on the final tree: 187 pass, 0 fail (
npm run gate: tsc + build + node --test).What I found first
The premise of the ask needs one correction: the dot-segment rule was already on main.
src/lib/paths.tsalready refused any segment beginning with., with its ownhidden path refusedmessage, andTEXT_EXTENSIONS/isTextPathwere already there and wired in. So there was nothing to re-cut from scratch — what was actually missing was (a) the ordering the brief calls for, and (b) coverage.What I changed
src/lib/paths.ts—relPath()re-cut around normalise-then-validate. Before, the..traversal check ran on the raw string and only the dot rule ran on the normalised one. That split held today only because backslashes are rejected outright; it's the kind of thing that quietly stops holding the moment someone relaxes that line. Now: the raw string is judged only for what normalising would destroy (empty, >300 chars, backslashes, control characters — a Windows path must be caught beforenormalizePathfolds\into/), then the path is normalised once and every segment rule reads that one normalised form. […]Gate
npm run gateran 187 tests in 2.4s and exited 0 — green.Built by Connor's backend backburner (dispatch
bdcb3dfb) in an isolated clone; shipped deterministically byship.py. The full build notes were spoken in conversation and stored in memory (agent-dispatch:bdcb3dfb). Review is the gate.The brief this build was given
Kept for provenance. This is the task the builder was dispatched with — not a description of the diff above.
On current obsidian-connor main, re-cut the relPath() hardening: reject any path whose segments begin with '.', so that dotfiles, dot-directories, '.' and '..' traversal are all refused rather than only '..' being stripped. Normalise before validating so encoded or mixed-separator forms cannot slip through. Add unit tests covering: plain '..' traversal, a leading-dot segment mid-path (e.g. 'notes/.git/config'), a leading-dot at the root ('.obsidian/plugins'), a bare '.', absolute paths, and the legitimate control cases that must still pass. Ship as a pull request. This task is one step of my plan: working-list item #57: Re-cut the two 89773b06 hardenings against current obsidian-connor main — relPath() must reject path segments beginning with '.', and read/list must be gated on a text-extension set; then sweep the five superseded stranded workdirs and fix the ledger's mislabelling Result of earlier step 1 (read in obsidian-connor: In the obsidian-connor repo, locate commit 89773b06 (likely on an abandoned or s): I could not save the file: this run is read-only (no Write tool), and `/home/joel/.local/state/connor/notes/` does not exist on disk. The finished writeup is below, ready to save verbatim. The headline is that the premise of item #57 is stale. ## First, a correction to what I thought I knew **`89773b06` is not a commit sha — it is a dispatch id.** It appears as one in my own run journal: `/home/joel/.local/state/connor/runtool-runs.jsonl:568-570` — `{"at": "2026-09-02T12:59:31+00:00", "dispatch": "89773b06", "target": "(discover)", "rc": 1}`, then two `rc: 0` runs at 13:02. Its workdir survives at `/home/joel/.local/state/connor/frontend-work/89773b06`, on a **local-only** branch `build/89773b06` (`.git/refs/heads/build/89773b06` → `1a08f083`). Its reflog holds exactly one commit: ```8b29e100→ 1a08f083 commit: build: add the streamable-HTTP MCP server to src/main.ts per the wire contract ``` So the "two hardenings" were never a hardening commit — they were details *inside* the stranded MCP-server build, which was superseded when the same feature landed as `caffc2c` (PR #1, `origin/feat/mcp-server`). That cut dropped both. My memory that "PR #8 landed commit 89773b06 in `src/ Built by my backend backburner (dispatch bdcb3dfb), diff verified by git; shipped by ship.py. Nothing merges without review.Independent review — reviewer-bot (local model
qwen2.5-coder:14b)The PR enhances path validation by rejecting paths with segments starting with dots and ensures the vault root is not treated as a note path. The changes are well-documented and include comprehensive tests.