Context
docs/threat-model.md was published with v0.5 (PR #17). It covers the attack surface at a sketch level — sufficient to tick the v0.5 exit criterion, not sufficient for a v0.9 RC sign-off. This issue tracked the original review work; concrete attack-path items have been spun out into their own issues. What remains here is housekeeping + the meta task of confirming the threat model reads cleanly cold.
Status of original items (verified 2026-05-06)
1. Input-size caps (#BR-8) — DONE (#40 closed)
2. Link safety verification (clet md) — moved to #91
Code mitigation is in place (MarkdownClet.cs lines 130–134, e.Handled = true, no Process.Start anywhere in src/). Missing integration test and threat-model doc update tracked in #91.
3. Terminal escape filter — moved to #92
Threat-model claim is aspirational; no filter exists in the code. Concrete attack paths and remediation tracked in #92.
4. File access boundary — moved to #93
Two surfaces (clet md as file-read primitive; pick-* --root not actually confining) detailed and tracked in #93.
5. Plugin loading — DONE (confirmed)
What remains in this issue
Housekeeping (low severity, no concrete attacker)
Threat-model doc cleanup (depends on #91 / #92 / #93 outcomes)
Meta — close-out criteria
A "reviewed" threat model means:
- Every attack surface in Appendix A has a corresponding test or a documented "won't fix / accepted risk" entry.
- A second set of eyes (another maintainer or a bar-raise pass) has read the document cold and found no unnamed surfaces.
This meta task should be the last box to tick on this issue, after #88 / #91 / #92 / #93 land.
Out of scope (deliberately)
Context
docs/threat-model.mdwas published with v0.5 (PR #17). It covers the attack surface at a sketch level — sufficient to tick the v0.5 exit criterion, not sufficient for a v0.9 RC sign-off. This issue tracked the original review work; concrete attack-path items have been spun out into their own issues. What remains here is housekeeping + the meta task of confirming the threat model reads cleanly cold.Status of original items (verified 2026-05-06)
1. Input-size caps (#BR-8) — DONE (#40 closed)
--initialat 64 KiB. Implemented inCommandLineRoot.csline 138 withcode: "input-too-large", exit 65.clet mdstdin at 8 MiB. Implemented inMarkdownClet.csline 80.specs/clet-spec.md§4.7 (line 285) and Appendix A (line 469).tests/Clet.SmokeTests/CletSmokeTests.cs(lines 104, 117) and unit tests inCommandLineRootTests.cs(lines 302, 316, 334) andExitCodesTests.csline 23.2. Link safety verification (
clet md) — moved to #91Code mitigation is in place (
MarkdownClet.cslines 130–134,e.Handled = true, noProcess.Startanywhere insrc/). Missing integration test and threat-model doc update tracked in #91.3. Terminal escape filter — moved to #92
Threat-model claim is aspirational; no filter exists in the code. Concrete attack paths and remediation tracked in #92.
4. File access boundary — moved to #93
Two surfaces (
clet mdas file-read primitive;pick-*--rootnot actually confining) detailed and tracked in #93.5. Plugin loading — DONE (confirmed)
Assembly.Load*/AppDomain/LoadAssembly— no matches anywhere insrc/. Confirmed 2026-05-06. Threat model claim holds.What remains in this issue
Housekeeping (low severity, no concrete attacker)
--outputfollows symlinks and truncates on error.src/Clet/Hosting/OutputFormatter.csopensnew StreamWriter(outputPath, append: false)which follows symlinks and unconditionally truncates. Even when the clet result iserror, the file is created/clobbered. ConsiderFileMode.CreateNew(or explicit overwrite confirmation) and skipping the file write on non-success status. Low severity in the trust model (CLI args are user-controlled), but the silent clobber on error path is a footgun.--<unknown>parser swallows the next token.src/Clet/Hosting/CommandLineRoot.cs~lines 197-209 accept any unknown--fooand consume the next token as its value. Soclet text --initial --output /tmp/xmakes--initialequal the literal string--outputand/tmp/xbecomes a positional arg. Should validatecletOptionskeys against the dispatched clet'sOptionsand reject unknown options withUsageError(exit 2). Mostly UX / agent-safety, no concrete security attack path.--initialsize cap runs before alias resolution.CommandLineRoot.cs~lines 132–146 emit aBoxedCletResulterror before the alias is checked. This conflates parsing errors (should be exit 2) with runtime errors. Reorder: resolve alias first, then bound-check.Threat-model doc cleanup (depends on #91 / #92 / #93 outcomes)
docs/threat-model.md"Terminal escape sanitization" section to describe what's actually filtered (after Security: implement terminal-escape filter for clet md content (and align threat model) #92 ships) instead of asserting a mitigation that didn't exist.Meta — close-out criteria
A "reviewed" threat model means:
This meta task should be the last box to tick on this issue, after #88 / #91 / #92 / #93 land.
docs/threat-model.mdby a second maintainer; surfaces any gaps as a follow-up or signs off.Out of scope (deliberately)