186 lines
9.3 KiB
Markdown
186 lines
9.3 KiB
Markdown
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
|
|
|
# Threat model
|
|
|
|
This document separates demonstrated behavior from intended release work. It
|
|
defines the boundary Sandwich Hime can reasonably defend; it is not a claim
|
|
that the project or an application using it is universally secure.
|
|
|
|
## Security objective
|
|
|
|
For supported HTML contexts, data supplied to a compiler-generated component
|
|
should remain data. It must not change HTML structure, create executable code,
|
|
escape a quoted attribute, or introduce a disallowed URL scheme unless trusted
|
|
application source makes an explicit security-sensitive decision.
|
|
|
|
That objective follows the same high-level model documented by Go's
|
|
`html/template`: template authors are trusted while rendered data is not. The
|
|
implementations and accepted languages differ. A systematic differential test
|
|
campaign against `html/template` remains open work; current tests cover fixed
|
|
adversarial cases and do not establish equivalence.
|
|
|
|
## Trusted capabilities
|
|
|
|
- `.sando` source, including its static markup and embedded Go statements;
|
|
- handwritten application Go and values whose formatting methods execute Go;
|
|
- handwritten implementations of `sando.Component`;
|
|
- explicit `sando.TrustHTML`, `TrustURL`, `TrustJS`, and `TrustCSS` calls;
|
|
- the selected compiler binary, Go toolchain, runtime module, and generated Go;
|
|
- local project code built and executed by `himesan dev`; and
|
|
- the user account, filesystem, environment, and other processes on the
|
|
development workstation.
|
|
|
|
Template semantics become trusted source when built into an application;
|
|
templates are not an untrusted-content sandbox. Someone allowed to edit one can
|
|
execute ordinary Go through the application build and must receive the same
|
|
trust as any other code contributor. Arbitrary or malformed template bytes
|
|
remain adversarial input to compiler robustness while they are being inspected.
|
|
|
|
A handwritten `sando.Component` is a trusted output capability. It may write
|
|
arbitrary bytes, change HTML parser context, recurse, block, panic, or perform
|
|
side effects. Hime-generated components are independently checked for balanced
|
|
HTML and may be inserted with `<?~` only at an HTML content boundary. The open
|
|
Go interface does not extend that proof to handwritten implementations.
|
|
|
|
The `Trust*` constructors do not sanitize. They record that trusted application
|
|
code accepts responsibility for the supplied bytes. `himesan check` emits
|
|
best-effort lexical audit hints for direct constructor/type use visible inside
|
|
`.sando` source; it is not Go type analysis, taint analysis, or a complete
|
|
inventory of trust created transitively in handwritten Go.
|
|
|
|
## Untrusted inputs
|
|
|
|
- ordinary values supplied to generated components;
|
|
- filenames and directory entries encountered during discovery;
|
|
- missing, stale, or manually modified generated output;
|
|
- browser requests reaching the development proxy;
|
|
- child-process output, exit behavior, and health failures; and
|
|
- malformed template bytes from a repository being inspected, provided the
|
|
template is not subsequently built and executed as trusted Go.
|
|
|
|
## Demonstrated controls
|
|
|
|
These are point-in-time implementation and test observations indexed to named
|
|
commits in the evidence ledger, not continuous assurance.
|
|
|
|
- Untrusted dynamic output is accepted only in supported HTML text, quoted
|
|
attribute, URL, and RCDATA contexts. Script and style interpolation requires
|
|
an explicit `TrustedJS` or `TrustedCSS` capability.
|
|
- Dynamic tag names, attribute names, unquoted values, event-handler values,
|
|
style attributes, foreign SVG/MathML content, URL lists, `srcdoc`, meta
|
|
refresh, malformed HTML, and ambiguous parser states are rejected.
|
|
- Ordinary text and quoted attributes are escaped; `title` and `textarea` use
|
|
an RCDATA writer that escapes every trusted wrapper as ordinary text.
|
|
- Ordinary whole URL values are normalized and checked before any bytes are
|
|
written. Schemes outside `http`, `https`, `mailto`, and `tel` fail unless a
|
|
`TrustedURL` deliberately bypasses that check.
|
|
- Writer errors and contract-violating short writes propagate to the caller.
|
|
- All sources in one operation are parsed/context-checked/formatted in memory
|
|
before the first output change. Each changed output is replaced atomically,
|
|
and existing destinations lacking the generated-file ownership marker, plus
|
|
symlink or non-regular destinations, are rejected. The marker prevents
|
|
accidents; it is not authentication against a hostile local actor.
|
|
- Recursive discovery skips VCS, vendor, symlink, nested-module, and detected
|
|
filesystem boundaries. Explicit files are still subject to no-symlink and
|
|
regular-file checks.
|
|
- `generate` and `check` do not invoke the Go toolchain, fetch dependencies,
|
|
execute project code, or edit `go.mod`. `himesan dev` is a separate command
|
|
that intentionally does all of generate, build, and execute trusted project
|
|
code.
|
|
- The development proxy binds to a literal loopback address, validates Host
|
|
authority, and checks Origin and Sec-Fetch-Site when those headers are
|
|
present. These checks are hardening, not a user-authentication boundary. Its
|
|
injected client is fixed and authorized with a hash rather than
|
|
`unsafe-inline`.
|
|
|
|
Executable tests and their latest maintainer-observed results are indexed in
|
|
[SECURITY_EVIDENCE.md](SECURITY_EVIDENCE.md).
|
|
|
|
## Important limits
|
|
|
|
### URLs
|
|
|
|
URL checking prevents disallowed or ambiguous schemes; it does not decide
|
|
whether a destination is authorized or trustworthy. `https:` and relative URLs
|
|
can still leave an origin, submit data, change a document base, or load active
|
|
content depending on the element and attribute. Applications must validate
|
|
destinations and apply tighter policy for sensitive sinks.
|
|
|
|
### Trusted raw values
|
|
|
|
`TrustedHTML`, `TrustedJS`, and `TrustedCSS` are intentional escape hatches.
|
|
Their authors must preserve the surrounding HTML parser state, including
|
|
container-closing and legacy parser-transition sequences. Prefer ordinary data,
|
|
keep trust conversion beside its validator, and review each use manually.
|
|
|
|
### Rendering resources and failures
|
|
|
|
The runtime does not impose output-size, recursion, CPU, allocation, or time
|
|
limits; recover panics; or make an arbitrary `io.Writer` transactional.
|
|
Applications should render into a buffer when an all-or-error HTTP body matters
|
|
and should apply their own request deadlines, bounded writers, input limits, and
|
|
panic policy. A context is passed through components, but generated output does
|
|
not automatically stop between writes when it is canceled.
|
|
|
|
The compiler likewise has no hard source-size, memory, or compile-time budget.
|
|
Run it only against repositories whose resource use the caller is willing to
|
|
accept.
|
|
|
|
### Filesystem concurrency
|
|
|
|
Discovery and generation defend against symlinks and non-regular files observed
|
|
at their checks. They are not currently a security boundary against a hostile
|
|
local actor racing path components between inspection and use. Run the compiler
|
|
inside a trusted workspace and user account. Atomic replacement describes each
|
|
file's visibility; a multi-file generation is not a filesystem transaction if
|
|
a later replacement fails.
|
|
|
|
The watcher is a development convenience, not a filesystem-integrity monitor.
|
|
It may miss adversarial changes engineered to preserve the metadata it samples.
|
|
|
|
### Development supervisor
|
|
|
|
Loopback is host-local, not user-local. The development supervisor has no user
|
|
authentication boundary against another process/account on the workstation. It
|
|
builds and executes project code with the user's inherited environment and may
|
|
fetch dependencies according to the user's Go configuration. It is not a
|
|
production proxy, public preview host, TLS terminator, deployment system, or
|
|
safe runner for untrusted repositories.
|
|
|
|
The watcher scans configured trees and eligible HTML responses may be buffered
|
|
up to 16 MiB for reload injection. The application and operating system retain
|
|
responsibility for request, response, SSE, file-count, and process resource
|
|
limits.
|
|
|
|
Development CSP rewriting is reload convenience, not production CSP
|
|
validation. Process cleanup is best-effort; a deliberately detached descendant
|
|
may outlive the process tree the supervisor can identify. Human-readable
|
|
diagnostics may also contain filenames or child-tool output supplied by a local
|
|
repository, so terminals and log consumers remain part of the trusted
|
|
development environment.
|
|
|
|
## Non-goals
|
|
|
|
Sandwich Hime does not:
|
|
|
|
- sandbox template authors or embedded Go;
|
|
- sanitize arbitrary trusted HTML, JavaScript, CSS, or URLs;
|
|
- provide application authentication, authorization, CSRF policy, CSP, routing,
|
|
database security, TLS, caching, or production process isolation;
|
|
- type-check all embedded Go during `himesan check` (the normal Go build/test
|
|
remains required);
|
|
- detect every dynamic or handwritten component cycle;
|
|
- guarantee safety under hostile concurrent mutation of the workspace; or
|
|
- replace independent review, browser testing, vulnerability response, or the
|
|
consuming application's threat model.
|
|
|
|
## Open release work
|
|
|
|
- broaden semantic and browser-parser differential testing;
|
|
- execute the Linux/amd64 and Darwin/arm64 security and process-lifecycle
|
|
release matrices;
|
|
- complete signed release provenance, checksums, and SBOM evidence;
|
|
- test the confidential reporting and signing-key recovery procedures; and
|
|
- close or explicitly accept every finding listed in the evidence ledger before
|
|
assigning a supported release line.
|