Date: 2026-09-05
Scope: untrusted .floe source → parser, IR, layout, SVG, CLI, LSP
Floe must never execute arbitrary source content.
.floe files are treated as untrusted. They may come from user uploads, AI generation, or external repos. The parser, validator, formatter, layout, renderer, CLI, and LSP must handle them without:
- code execution (
eval,new Function,vm,child_process.execon content) - XSS via SVG
- resource loading (images, scripts, network)
- path traversal beyond explicit file args
- ReDoS / infinite loop / memory exhaustion
- Scan:
grep -R "eval\|new Function\|require.*vm"acrosssrc/+dist/src→ 0 hits (Session 05security.test.tsalso asserts). - Parser: hand-written recursive descent over
Lexertokens; never interpolates source into JS code. - Formatter / Layout / Renderer: pure string manipulation; no
Functionconstructor. - CLI/LSP: read file via
fs.readFileSync(path, "utf-8")only; neverrequireorimportfile content. - Verdict: No high/medium issues. Low future risk (link href) mitigated.
- Escaping:
escapeXmlfor&<>\"',escapeAttr,escapeId(non-alnum →_),hashLabel. No<script>,<foreignObject>,onloadetc in template.tests/security.test.tsverifies"<script>"→<script>. - Child process:
src/cli/main.ts:185dynamicimport("../lsp/server.js")only forfloe lsp(trusted path). Nochild_process.execon.floecontent.
- Sanitization:
security/url.ts: sanitizeUrlallows onlyhttp://,https://,mailto:,/path, or scheme-less relative.validator.jsflagsjavascript:asE014.
- Reads:
fs.readFileSynconly, neverrequire. - Writes:
fs.writeFileSynconly for explicitformat --write/render -o.
bun run test387 tests includesecurity.test.ts+fuzz.test.ts(1000+ random) — no crash.
- Add
SECURITY.mdroot if needed for GitHub.