4.7 KiB
Security and privacy policy
EventLens is a defensive, local/self-hosted Windows Event Log analysis tool. It is designed for bounded incident reconstruction, not for centralized log retention or alerting.
Data handling
- The selected
.evtxfile is processed at the request boundary and is not intentionally persisted by EventLens. - FastAPI/Starlette may use a transient multipart spool while receiving a request; the upload handle is explicitly closed in a
finallyblock and EventLens does not copy it to an application file. - Analysis state lives in browser component memory for the current session. Only non-sensitive UI preferences are stored in the single
eventlens.preferences.v1localStorage record; the Settings workspace exposes that boundary, saves preferences automatically and resets only that record. EventLens never stores event text, EVTX-derived values or analysis results there. There is no application database, account system, telemetry, analytics, cloud storage or third-party event upload. - API and health responses use
Cache-Control: no-store; API responses also usePragma: no-cache. - The API sanitizes uploaded filenames to a short basename before returning them. Export filenames are sanitized in the browser.
- Event contents are not written to application logs. Runtime logs contain request paths/statuses only.
Untrusted input controls
The EVTX/XML boundary is hostile-input handling, not trusted document parsing. The current limits are:
- 50 MiB file cap plus a 51 MiB request-envelope gate enforced while ASGI body messages are received, independent of
Content-Length; - 100,000 normalized-event cap;
- cooperative 8-second parser budget;
- 2 MiB per parser-record JSON cap;
- 200 normalized fields per event;
- 256-character provider/channel/computer and 512-character summary caps;
- 1,000-character normalized field-value cap, bounded field keys and a 16 MiB normalized-output budget;
- deterministic single-thread parser execution with a process-local bounded admission gate (one active parse by default, with a configurable queue capped at four waiting requests);
- generic parser errors and generic skipped-record issues without raw exception/event payloads; unexpected programmer/parser failures are logged only with stage, exception class and a non-data fingerprint and return a generic client error;
complete,partialandfailedparse status. Partial status means records were omitted or parser recovery/truncation occurred; timestamp-quality notes alone do not make a complete record set look partial.
Malformed/corrupt files are rejected when no event can be recovered; partial recovery is marked in parse statistics. The Rust-backed evtx parser remains an external parser dependency and is isolated behind the parser module.
Presentation and export safety
- Raw XML is never returned to or injected into the UI. The inspector exposes the normalized JSON contract.
- React renders event text as values, not HTML.
- Redaction works on a clone and previews host, identity, e-mail, IPv4/IPv6, Windows/UNC path and source-name replacements before export. Known structured identities are propagated into summaries, incident titles and reasons; domain accounts, SIDs and machine accounts are covered conservatively.
- Markdown exports treat every event value as untrusted text: headings, links, images, HTML, tables and code-fence delimiters are escaped or placed inside a safe dynamic code span.
- Redaction is best-effort; users must inspect reports before external sharing.
- Correlation copy explicitly describes evidence-supported relationships and does not claim causality.
Dependency and release controls
- Frontend release installs use
frontend/package-lock.jsonandnpm ci. - Python release installs use
backend/uv.lockanduv sync --locked. - Base images are pinned by manifest digest in
Dockerfile; the maintenance task is to update the tag and digest together and rerun the full validation. - CI runs Ruff, backend tests with deprecation warnings treated as errors,
pip-audit, frontend lint/tests/typecheck/build,npm audit, deterministic Playwright journeys, Docker runtime smoke, a Trivy high/critical image scan and a CycloneDX image SBOM generation step. - The real-EVTX CI fixture is fetched from a pinned upstream tag and accepted only when its EVTX magic and SHA-256 match the recorded value.
- The runtime container is non-root, read-only-compatible, uses a bounded
/tmp, drops all Linux capabilities and enablesno-new-privileges.
Reporting issues
Use synthetic or already-public event samples. Never attach production logs containing credentials, personal data, confidential hostnames or internal network details to a public issue. Describe the smallest reproducible input and remove raw event payloads from screenshots and logs.