# 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 `.evtx` file 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 `finally` block 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.v1` localStorage 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 use `Pragma: 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`, `partial` and `failed` parse 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.json` and `npm ci`. - Python release installs use `backend/uv.lock` and `uv 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 enables `no-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.