# Security model SVG is active content. Threats include script/event execution, navigation, external fetches and tracking, CSS resource resolution, `foreignObject`, native animation triggers, namespace confusion, entity/DOCTYPE processing, parser differentials, oversized compressed/data content and algorithmic complexity. ## Source and projection Canonical source is inert text and remains available even when unsafe. A separate projection is built from a cloned semantic document. DOMPurify's SVG profiles are followed by an application policy that: - removes `script`, `foreignObject`, `animate`, `animateMotion`, `animateTransform`, `set`, foreign namespaces and all `on*` attributes; - disables links/navigation and executable or external URL attributes; - allows only unique local fragment references and bounded base64 raster image data (`png`, `jpeg`, `gif`, `webp`, `avif`); - parses style declarations/stylesheets with css-tree and rejects `@import`, unsafe legacy properties, parse failures, non-local URLs, `expression()` and resource-producing functions such as `image-set()` and `paint()`; - reports findings with source ranges wherever a semantic node/range exists. DOCTYPE is excluded before DOM parsing; entity declarations invalidate the semantic projection. Sanitized export removes temporary mapping attributes. Sanitize is never applied to canonical source without preview and acceptance. ## Isolated preview The projection is an iframe `srcdoc` with `sandbox="allow-scripts"` and no `allow-same-origin`, giving it an opaque origin. Its child CSP is: ```text default-src 'none'; connect-src 'none'; object-src 'none'; frame-src 'none'; base-uri 'none'; form-action 'none'; img-src data: blob:; style-src 'unsafe-inline'; script-src ``` The sole script is the packaged `canvas-frame-controller.js`. It is loaded with anonymous CORS, accepts messages only from `parent` with a random channel, validates message fields and removes its script element. The parent validates both `event.source` and channel. Because a sandbox without same-origin treats the script request as cross-origin, serve this one app-relative asset with: ```text Access-Control-Allow-Origin: * Cross-Origin-Resource-Policy: cross-origin ``` Keep `Cross-Origin-Resource-Policy: same-origin` for other files. Use an Nginx `map`/header value, not a nested `location` that would drop inherited security headers. Toolbox Portal 0.10.0 implements and tests this exception. ## Limits and tests Hard limits are defined in `src/app/limits.ts`. SVGZ uses streaming decompression and stops once output crosses the source limit. Workers are revisioned, timed out and cancelable. Tree/diagnostic rendering is capped. Project-authored tests cover script, handlers, links, external image/use/filter, CSS imports/URLs/parser failures/resource functions, native animation, namespaces, duplicate IDs/cycles, malformed entities/XML, depth/attribute/path and data limits. Browser tests assert no script callback and no request to the hostile domain. ## Limitations and reporting This policy protects this application's projections and exports; it is not a general guarantee for arbitrary downstream embedding. Browser SVG/CSS parsers and DOMPurify remain dependency/security boundaries. Bounded data URLs may still decode expensive images within the raster-pixel limits. CSP header regressions can break the fixed controller even when the content remains inert. Report vulnerabilities privately through the repository owner/contact before opening a public issue when disclosure could expose users. Include the SVG, browser, deployment headers and observed network/execution behavior without sensitive user files.