# Security Policy

## Supported release

Security fixes are provided for the current release line. This package is version `1.2.1`.

## Reporting

Report a vulnerability privately to the contact configured in `config/site.php`. Include the affected route, expected and observed behavior, browser/runtime, minimal reproduction, and likely impact. Do not include secrets or test against systems outside the supplied application.

## Safe testing scope

Permitted on an authorized local or staging copy:

- static review;
- PHP and JavaScript linting;
- API schema, CSRF, sequence, request-size, and rate-limit tests;
- browser compatibility, accessibility, and rendering-fallback tests;
- attempts to submit non-allowlisted challenge IDs, commands, evidence IDs, hypotheses, controls, or malformed JSON;
- attempts to load non-allowlisted Atlas filter, record, comparison, timeline, or evidence-state values;
- verification that Atlas query text is escaped and never interpreted as markup;
- verification that internal directories and sensitive artifacts are inaccessible.

Not permitted:

- denial-of-service against a public host;
- credential attacks or account testing;
- probing unrelated domains, APIs, networks, or infrastructure;
- substituting real targets, live indicators, exploit payloads, malware, or weapon parameters;
- social engineering or collection of visitor data.

## Security architecture

### Request controls

- 16 KiB maximum JSON request body;
- JSON object requirement and bounded decode depth;
- CSRF token validation for state-changing simulation requests;
- per-session command rate limit;
- strict challenge/scenario identifier patterns;
- allowlisted commands and server-side phase preconditions;
- non-negative expected sequence and HTTP 409 resynchronization;
- no arbitrary URL, command, script, file, or state fields.

The Atlas has no POST endpoint or state-changing API.

### Session controls

- HttpOnly session cookie;
- SameSite=Lax;
- Secure flag under HTTPS;
- server-authoritative simulation state;
- no account database or persistent authentication token;
- separate state keys for each challenge and deterministic seed.

Atlas filtering and comparison do not use the PHP session.

### Browser controls

- nonce-based Content Security Policy;
- no object embedding or frame ancestors;
- microphone, camera, geolocation, payment, and USB disabled;
- WebXR and fullscreen limited to self;
- external scripts limited to the pinned Three.js CDN when enabled;
- Canvas and semantic HTML fallbacks if that dependency fails;
- Atlas uses local HTML/SVG/JavaScript only and makes no map, geocoder, or dataset request.

### Atlas data and URL controls

- all publication records are curated in non-public PHP data files;
- record IDs, evidence states, functions, control modes, lifecycle states, regions, event types, and comparison references are validated against allowlists derived from the release dataset;
- unknown URL values fall back to safe defaults instead of creating records or HTML;
- search text is length-bounded and compared as text only;
- embedded JSON uses PHP JSON hex escaping;
- comparison rows and chips are created through `textContent`, not `innerHTML`;
- the comparison list is capped at four entities;
- copied views contain only the current public URL state and are generated after explicit action;
- map positions are abstract percentages and not geographic coordinates;
- source links come only from the curated source registry.

### Content controls

- curated static challenge and Atlas catalogs only;
- no uploads, remote scenario imports, executable fields, or user-authored markup;
- correct answers and control quality removed from pre-resolution challenge API payloads;
- no real targets, exact coordinates, casualty models, weapon optimization, executable cyber content, or external actions;
- no capability or lethality score generated by the Atlas comparison.

## Deployment checks

Before production:

1. use HTTPS and a supported patched PHP runtime;
2. confirm PHP session storage is private and writable;
3. verify `/config/`, `/data/`, `/includes/`, `/storage/`, `/tests/`, and `/realtime/` are denied;
4. verify CSP, `nosniff`, frame denial, Referrer-Policy, COOP, and Permissions-Policy headers;
5. run `tests/smoke.sh` and the browser smoke test;
6. test Atlas query manipulation, synchronized table behavior, and mobile layout;
7. update canonical origin and contact address;
8. review host access/error log retention, including requested URLs with Atlas query strings;
9. retain the release checksum and source archive.

## Known architectural limits

- Session state is single-host and not appropriate for a load-balanced deployment without shared session storage.
- The request rate limit is session-based, not a replacement for host-level abuse controls.
- The external Three.js dependency is integrity-pinned by version URL but not bundled locally; the Canvas fallback preserves function if it fails.
- Browser-local challenge progress can be changed by the user and is not an assessment credential.
- Result cards are informational artifacts, not cryptographically signed certificates.
- Atlas saved views are ordinary URLs, not signed evidence packages. Query strings may appear in browser history, copied messages, referrer handling, and host logs.
- Atlas evidence labels summarize public records and do not eliminate the need to read the source trail, limitations, and unknowns.

## Repository-memory exposure boundary

The release package contains `AGENTS.md`, `.uai/`, `docs/long-term-memory/`, and `agent-file-handoff/` for repository continuity. They are not public content and must be denied by Apache/LiteSpeed or equivalent Nginx rules. A live proof must confirm they return a denial and do not expose reports, internal paths, handoff material, or credential inventory metadata.
