mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-18 16:46:17 +00:00
The previous filepath.IsLocal-up-front pattern in safeJoin/safeJoin-equivalents turned out not to satisfy CodeQL's go/path-injection rule — the post-validation filepath.Join still constructs the joined string from tainted input, so the analyser conservatively assumes the os.* sink that consumes it is tainted too. Only one of 34 alerts closed on the previous attempt. Switch to *os.Root (Go 1.24+, available on the project's 1.26.3 toolchain). The Go runtime guarantees that operations on a Root cannot escape the anchored directory regardless of what's in the relative path, and CodeQL has a built-in model that recognises *os.Root.* methods as path-traversal sanitisers. Result: every os.* sink in the datastore, marge, recorder, mirror parity-mismatch writer, and docs handler is now reached only via a *os.Root, which closes the rule-level alerts cleanly. Changes per file: * pkg/service/datastore/datastore.go — Adds a `root *os.Root` to DataStore, lazily opened at first use (after MkdirAll-ing baseDir) and closed by a new `(*DataStore).Close()`. Adds package-private helpers (rootStat / rootReadFile / rootWriteFile / rootMkdirAll / rootRemove / rootRemoveAll / rootRename / rootReadDir / rootOpen / rootExists) plus three exported wrappers (ReadDirUnderBase, MkdirAllUnderBase, WriteFileUnderBase) for the cross-package marge / handlers callers. Every os.* call that previously consumed safeJoin output now goes through these helpers. The post-join belt-and-suspenders prefix check inside safeJoin is preserved as a defence-in-depth fallback. * pkg/service/marge/marge.go — Replaces the five `os.ReadDir(devicesDir)` call sites with `ds.ReadDirUnderBase(...)` so the datastore's root enforces containment. * pkg/service/proxy/recorder.go — Mirrors the datastore pattern with its own `root *os.Root` anchored at Recorder.BaseDir, lazily opened. New helpers convert the eight existing `os.*` sites that consume sessionID / relPath / sanitizedSegments inputs. The earlier safeJoin (filepath.IsLocal pre-check) stays in place as the same belt-and-suspenders guard. * pkg/service/handlers/handlers_docs.go — Opens a *os.Root at "docs" via sync.Once and reads file content (and SUMMARY.md sidebar) through it. Removes the prior filepath.IsLocal pre-check; the runtime now guarantees containment. * pkg/service/handlers/mirror_middleware.go — Routes the parity-mismatch JSON write through `s.ds.WriteFileUnderBase` so the datastore's root performs the path-traversal sanitiser. Behavioural fix: *os.File.ReadDir(-1) returns directory entries in filesystem order, but os.ReadDir is documented to sort by name and at least one regression test (handlers.TestMargeAccountFullExcludesEmptyAmazonSource) depends on the sorted contract. Both rootReadDir helpers explicitly sort by name to match. All test suites pass for the touched packages; the unrelated TestDocsConsistency failure about untracked working-tree docs is pre-existing. golangci-lint reports 0 issues. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>