From d1267b6bbaedb2e8a4ea622d3f0d61e6ff7e686e Mon Sep 17 00:00:00 2001 From: Xuepoo Foter <144407384+Xuepoo@users.noreply.github.com> Date: Tue, 6 Oct 2026 02:59:05 +0800 Subject: [PATCH] [CTX-0281] docs(security): add filesystem family matrix and P0-AC scope notes (RFC-0005 gate) --- docs/security/p0-acceptance-criteria.md | 33 +++++++++++++++++++++++ docs/security/threat-model.md | 36 +++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/docs/security/p0-acceptance-criteria.md b/docs/security/p0-acceptance-criteria.md index 2ff15b9..ec803c0 100644 --- a/docs/security/p0-acceptance-criteria.md +++ b/docs/security/p0-acceptance-criteria.md @@ -228,6 +228,11 @@ History-read family scope (RFC-0004 draft): a history-read query fault (over-bound, over-rate, scope mismatch, or revoked grant) is contained to the calling plugin VM; the host survives and other plugins are unaffected. +Filesystem family scope (RFC-0005 draft): a filesystem operation fault +(over-bound, over-rate, scope mismatch, revoked grant, sensitive-path +denial, or secret-shaped refusal) is contained to the calling plugin VM; +the host survives and other plugins are unaffected. + ### P0-AC-014 Plugin resource budgets attributable Source: plugin system "Runtime isolation"; baseline "Plugins". Risk: R-007. @@ -397,6 +402,14 @@ plugin VM never implies clipboard, filesystem, process, or external-history authority, each of which needs a separately granted authority with argv-first external invocation and no shell-string construction. +Filesystem family scope (RFC-0005 draft): every filesystem read and listing +result carries a Core-attached typed untrusted-observation label that +survives redaction, truncation, and attribution; labeled content is never +executed, interpolated, or routed into an instruction channel. Delivery into +the plugin VM never implies clipboard, process, IPC, or network authority, +each of which needs a separately granted authority, and process invocation +over file content stays argv-first with no shell-string construction. + ### P0-AC-025 DevTools scopes distinct and ungranted by connection Source: threat model "MCP, Agents, and DevTools". Risk: R-014. @@ -489,6 +502,11 @@ requesting the history-read family is a capability increase and blocks pending an explicit permission diff and approval; no grant migrates from `terminal.*` to the history-read family or back in either direction. +Filesystem family scope (RFC-0005 draft): a plugin update newly requesting +the filesystem family is a capability increase and blocks pending an +explicit permission diff and approval; no grant migrates from `terminal.*` +to the filesystem family or back in either direction. + ## Configuration trust and origin policy ### P0-AC-031 Project configuration declarative by default @@ -583,6 +601,21 @@ name the level and the family only with no content bytes or absent-versus-denied signals. Exact identifiers stay parked to W-139; this criterion covers admission shape only. +Filesystem family scope (RFC-0005 draft, OQ-085): the candidate filesystem +family maps to the `filesystem` domain and grants no other domain +authority. Effective authorization applies the threat-model filesystem +admission table before the grant intersection: L0 allowed as the enforcer; +L1 and L2 allowed only with an explicit per-plugin grant carrying explicit +path patterns and intersecting operation scope; L3 allowed only through an +explicit per-request Core-issued grant; L4 denied by default with only +explicit per-invocation grants. Verification extends the matrix to every +L0–L4 × filesystem cell with allowed or denied plus rationale; denials name +the level and the family only with no content bytes or absent-versus-denied +signals, and listings suppress denied entries silently. This admission mints +no identifier and covers the family shape only; exact spellings, payload and +listing caps, rates, and label encoding stay parked to the Core bridge and +SDK implementation. + ### P0-AC-036 Secret-tier consent, audit, and redaction Source: threat model "Secret-storage tiers" (OQ-055); overview "Sensitive diff --git a/docs/security/threat-model.md b/docs/security/threat-model.md index 1edb9e7..3b8d2c1 100644 --- a/docs/security/threat-model.md +++ b/docs/security/threat-model.md @@ -141,6 +141,42 @@ review plus docs-curator approval per RFC-0004 acceptance evidence. Denials name the level and the family only and carry no content bytes, foreign identifiers, or absent-versus-denied signals. +#### Filesystem family admission (RFC-0005 draft, OQ-085) + +The candidate filesystem (`fs`) family maps to the `filesystem` domain: +bounded, self-contained reads, writes, and listings strictly inside explicit +path patterns. It grants no process, network, clipboard, IPC, `terminal +input`, `terminal output`, or other domain authority, and a grant in one +domain never implies authority in another; a `terminal.*` grant never implies +a grant in this family and vice versa. The decided verb set is read, write, +and list: `list` is read-class and rides the read grant over the listed +prefix, while `open` and `append` are rejected as verbs. This admission mints +no capability identifier and changes no grammar: the accepted +`fs.read:PATTERN` and `fs.write:PATTERN` split stays the single authority +with the parameter required and no family-wide wildcard. Exact Lua +spellings, per-call payload and listing caps, operation rates and quotas, +redaction format, and label encoding stay parked to the Core bridge and SDK +implementation; this admission covers the family shape only and authorizes no +implementation. Acceptance requires independent security review plus +docs-curator approval per RFC-0005 acceptance evidence. + +| Level | Filesystem family admission | Rationale | +| ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| L0 | Allowed — Core owns enforcement (grant gate, bound enforcement, redaction and truncation, typed denials). | L0 admits `filesystem`; Core is the enforcement point and no plugin grant confers Core authority. | +| L1 | Allowed only with an explicit per-plugin grant carrying explicit path patterns recorded by Core; the operation path must intersect the grant scope; reads, writes, and listings are bounded self-contained requests, redacted, truncated, and labeled untrusted. | L1 admits `filesystem`; deny-by-default is preserved and safe-mode, scope-mismatch, sensitive-path, secret-shaped, hostile-pattern, and over-bound or over-rate requests deny fail-closed with a typed denial. | +| L2 | Allowed only with an explicit per-plugin grant carrying explicit path patterns recorded by Core; the operation path must intersect the grant scope; reads, writes, and listings are bounded self-contained requests, redacted, truncated, and labeled untrusted. | L2 admits `filesystem` and is the primary consumer (file-manager, editor preview, and mediated Wheel reads); no grant migrates from `terminal.*` in either direction and a newly requested family blocks updates per P0-AC-030; `list` never becomes a grant-free enumeration oracle. | +| L3 | Allowed only through an explicit per-request grant issued by Core to a verified native component coprocess; no standing grant exists. | L3 admits `filesystem` at the domain level; the sidecar stays out-of-process with descriptor and digest verified before every spawn, never resolved through `PATH`, and never widening its grant. | +| L4 | Denied by default — no standing admission; acts only through an explicit per-invocation grant. | L4 admits none by default per OQ-085 and the family grants no L4 authority; unknown levels or domains also deny rather than default. | + +Denials name the level and the family only and carry no content bytes, +foreign identifiers, or absent-versus-denied signals. Listings suppress +denied entries silently (silent skip) as the default; any alternative shape +must preserve the no absent-versus-denied signal rule above. Reads never +imply writes and writes never imply read-back; reading or listing under this +family authorizes delivery of results into the plugin VM only, and no watch, +subscription, tail-follow, retained handle, or cross-call cursor exists in +this family. + ### Secret-storage tiers (OQ-055, SEC-22) Secrets live in exactly one of four tiers, with policy that only tightens