# CSP Report Review (PROD, 2026-08-03) Review of Content-Security-Policy-Report-Only violations from PNSPS PROD (`https://pnsps.gld.gov.hk`), for deciding Apache CSP updates. Source logs (external): - `PNSPS PROD CSP Report 2026-08-03.txt` - `summary.txt` - `CSP Issue 1.txt` (`script-src` / `eval` samples) Related app docs: - [csp-apache.conf.md](./csp-apache.conf.md) — Apache header snippets to deploy --- ## Policy in effect at report time ``` default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; style-src-elem 'self' 'unsafe-inline'; img-src 'self' data: https://www.w3.org https://w3.org; media-src 'self' blob:; font-src 'self' data:; connect-src 'self'; upgrade-insecure-requests; report-uri https://pnsps.gld.gov.hk/api/csp-report ``` Notes: - Disposition was `report` (Report-Only); nothing was enforced. - No `frame-src` → framing falls back to `default-src 'self'`. --- ## Summary of findings Most reports are **browser / extension noise**. Only one directive change is required for **app functionality**: add `frame-src`. | Approx. volume | Directive | Blocked | Verdict | |---:|---|---|---| | ~3000 | `frame-src` | empty / `data:` (URI often stripped) | **App** — PDF preview iframes | | ~1500 | `script-src` | `wasm-eval` | Noise — `chrome-extension` | | ~1400 | `font-src` | `fonts.gstatic.com` (Inter / Nunito) | Noise — not app fonts | | ~500 | `img-src` | `https://www.w3.org/WAI/wcag2AA` | Already allowed; mostly doc `404` noise | | ~240 | `font-src` | `at.alicdn.com`, `cdn.yiban.io`, Perplexity CDN | Noise — toolbars / extensions | | ~180 | `style-src-elem` | `fonts.googleapis.com` | Noise — not loaded by app | | ~70 | `script-src` | `eval` (line ~67) | Noise — no app `eval` | | rest | various | Kaspersky, Youdao, Quark, `todesktop-internal`, etc. | Noise | App fonts are self-hosted (`@fontsource` Public Sans / Noto; see `public/index.html` and `src/assets/fonts.css`). Google Fonts (Roboto / Inter / Nunito) are **not** part of the app and must not be allowlisted. --- ## App-owned issue: `frame-src` ### Cause Proof upload preview in `src/pages/Proof/Create_FromApp/UploadFileTable.js`: 1. `FileReader.readAsDataURL(...)` builds a `data:` URL 2. `window.open("")` then `document.write` an `