Development record
cli.Run now routes all command errors through the --json envelope, so any verb that returns a bare *fs.PathError (os.ReadFile/os.Open failures not wrapped by core) emits the absolute local path into machine JSON output, violating no-absolute-paths-in-machine-output. iss-29 sanitised the docs-lint config-load branch specifically; the systemic fix is to sanitise PathError-bearing errors at the Run() boundary (or audit which errors reach the envelope). Detector: a table test that runs each verb's known filesystem-error path under --json and asserts the envelope carries no absolute path. Pre-existing as stderr text; newly widened to --json by cli.Run.
cli.Run now routes all command errors through the --json envelope, so any verb that returns a bare *fs.PathError (os.ReadFile/os.Open failures not wrapped by core) emits the absolute local path into machine JSON output, violating no-absolute-paths-in-machine-output. iss-29 sanitised the docs-lint config-load branch specifically; the systemic fix is to sanitise PathError-bearing errors at the Run() boundary (or audit which errors reach the envelope). Detector: a table test that runs each verb's known filesystem-error path under --json and asserts the envelope carries no absolute path. Pre-existing as stderr text; newly widened to --json by cli.Run.
Frontmatter
| id | iss-76 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | minor |
.abcd/work/issues/resolved/iss-76-json-error-abspath-leak.md
open on GitHub ↗ · commit history ↗
mentions2
- iss-29fail-closed capture surface: a misspelled capture subcommand (e.g. capture resovle) is swallowed as capture text and files a NEW issue instead of erroring (internal/surface/cli/cli.go:455) — a typo becomes a ledger mutation; --json errors emit raw Go text, not JSON (internal/surface/cli/cli.go:165), and abcd docs lint without a config surfaces a raw file error. Detector (per unrecognized-input-never-writes): a surface test convention where every mutating verb has a malformed-input case asserting an error, a did-you-mean for near-misses, and no write occurred, plus a --json error-shape contract test. Acceptance corpus: the three instances above — the detector is proven when it flags all three.
- iss-81Machine output surfaces absolute local paths OUTSIDE the cli.Run error-identity scrub added in iss-76. Two instances found in the iss-76 security re-review: (1) 'memory ingest <abs-path>' — materialFromLocal EvalSymlinks-resolves the user's source argument and embeds the resolved absolute path in a custom IngestError (internal/core/memory/ingest.go:655,658,663,667). It lies outside cwd/home, so scrubPaths' root-redaction and PathError base-name reduction both miss it. Low severity: it is the user's own argument and carries no developer identity for out-of-home paths (a ~/x argument still redacts to ~/x). (2) STRONGER, separate surface: the capture SUCCESS envelope emits an absolute 'path' field, e.g. {"path":"<home>/.abcd/work/issues/open/iss-N-...md"} — a full home/cwd-rooted path emitted unbidden on the SUCCESS path, which the error-only scrubPaths never sees. Detector (per unrecognized-input-never-writes / no-absolute-paths-in-machine-output): extend the per-verb --json table to assert no absolute path in BOTH the success and error envelopes for verbs echoing store/source paths; fix by rendering repo-relative or base-name paths at those sites. Acceptance corpus: the ingest error sites and the capture success 'path' field above.