Report privately through GitHub Security Advisories. Please do not open a public issue for anything in the first category below.
Expect an acknowledgement within a week.
Backlight parses deliberately hostile files, so parser safety is the core of its threat model:
- Denial of service through a crafted document — a file that hangs the scanner, exhausts memory, or makes the browser tab unresponsive. Decompression bombs, XML entity expansion, pathological object graphs, cyclic references.
- Anything that causes the web version to transmit file contents. The privacy claim is load-bearing; a bug that breaks it is the most serious class of report here.
- Cross-site scripting through document content. Findings quote text taken from adversarial files. Any path where that text reaches the DOM unescaped is a vulnerability.
- Path traversal or arbitrary write in the CLI, including through document-supplied names.
- A technique the scanner misses. Open a normal issue with a sample built using a labelled canary marker rather than a real payload — see CONTRIBUTING.md.
- A false positive on a legitimate document. These genuinely matter; a scanner nobody trusts protects nobody.
- The scanner not catching a technique it does not implement yet. That is a feature request, and the roadmap in PLAN.md is honest about what is not built.
- A clean report on a document that is dishonest in content. Backlight detects concealment, not untruth.
- No network. The core package makes no network calls and the web build is fully static. There is no server component and no upload path.
- Bounded decompression. OOXML packages are size-capped per part and in total before decompression; PDF stream decoding is capped at 128 MB.
- No entity expansion. The OOXML reader is a purpose-built scanner that never resolves
DOCTYPE, never expands entities beyond the five predefined ones plus numeric character references, and never follows an external reference. XXE and billion-laughs are closed by construction, not by configuration. - Bounded parsing. Recursion depth, object-graph cycles, form-XObject nesting and operator
counts are all bounded. A detector that throws is caught and reported in
engine.erroredrather than aborting the scan. - Evidence is escaped. All quoted document text passes through
evidence(), which visualizes control and invisible codepoints and truncates, before it reaches any output.