# Security Hardening Profile

Date: 2026-04-26

This profile records the compatible production hardening controls reviewed for P7-DEBT-05.

## HTTP Headers

| Surface | Current control |
|---|---|
| Admin page | `Content-Security-Policy` limits default/script/style/image/font/connect sources while allowing required legacy inline script/style execution. |
| Admin page | `X-Frame-Options: SAMEORIGIN`, `X-Content-Type-Options: nosniff`, and `Referrer-Policy: strict-origin-when-cross-origin`. |
| AJAX endpoint | JSON content type, `X-Frame-Options: DENY`, `X-Content-Type-Options: nosniff`, and strict referrer policy. |
| Widget init | `X-Frame-Options: SAMEORIGIN`, `X-Content-Type-Options: nosniff`, and strict referrer policy. |

The admin CSP intentionally keeps `'unsafe-inline'` and `'unsafe-eval'` because the legacy admin UI and bundled editor/chart tooling still rely on inline snippets and dynamic script behavior. Removing those sources should be a separate frontend modernization task.

## Cookie Controls

`sb_set_cookie_login()` sets the login cookie with:

- `HttpOnly`
- `SameSite=Lax`
- `Secure` when the request is HTTPS
- 30-day expiry aligned with token expiry checks

Production requirement: terminate TLS before PHP or set HTTPS forwarding correctly so PHP can detect secure requests.

## AJAX Abuse Controls

- Unknown AJAX functions default-deny through the registry/security checks.
- Batch calls must be valid JSON arrays.
- Batch calls are capped at 20 calls per request.
- Batch request state is reset between items to prevent parameter bleed.

## Residual Hardening Backlog

- Replace inline admin scripts/styles so CSP can remove `'unsafe-inline'` and `'unsafe-eval'`.
- Add per-IP or per-session request-rate limits for high-risk AJAX mutations after target-host traffic patterns are known.
- Add proxy-aware secure cookie detection if the production load balancer does not pass `HTTPS=on` to PHP.