Bladeren bron

update for CSP config

master
Jason Chuang 1 maand geleden
bovenliggende
commit
720fdbf9c4
3 gewijzigde bestanden met toevoegingen van 217 en 1 verwijderingen
  1. +4
    -1
      docs/csp-apache.conf.md
  2. +1
    -0
      docs/csp-report-review-2026-08-03.md
  3. +212
    -0
      docs/csp-report-review-2026-08-14.md

+ 4
- 1
docs/csp-apache.conf.md Bestand weergeven

@@ -4,7 +4,10 @@ Self-hosted fonts: no `fonts.googleapis.com` or `fonts.gstatic.com`. Static asse

Adjust `report-uri` if your API base path or host differs (UAT example below; PROD uses `https://pnsps.gld.gov.hk/api/csp-report`).

See also: [csp-report-review-2026-08-03.md](./csp-report-review-2026-08-03.md) for the PROD report analysis that drove `frame-src` / `media-src` updates.
See also:

- [csp-report-review-2026-08-14.md](./csp-report-review-2026-08-14.md) — latest PROD + UAT report review and add/remove summary
- [csp-report-review-2026-08-03.md](./csp-report-review-2026-08-03.md) — earlier PROD report analysis that drove `frame-src` / `media-src` updates

## Enforcing



+ 1
- 0
docs/csp-report-review-2026-08-03.md Bestand weergeven

@@ -12,6 +12,7 @@ Source logs (external):
Related app docs:

- [csp-apache.conf.md](./csp-apache.conf.md) — Apache header snippets to deploy
- [csp-report-review-2026-08-14.md](./csp-report-review-2026-08-14.md) — later PROD + UAT review (add/remove summary)

---



+ 212
- 0
docs/csp-report-review-2026-08-14.md Bestand weergeven

@@ -0,0 +1,212 @@
# CSP Report Review (PROD + UAT, 2026-08-14)

Review of Content-Security-Policy-Report-Only violations from PNSPS PROD
(`https://pnsps.gld.gov.hk`) and UAT (`https://pnspsuat.gld.gov.hk`), for
deciding Apache CSP updates.

Source logs (external):

- `P1 CSP.txt` — PROD node, 168 reports, 2026-07-30 to 2026-08-14
- `P2 CSP.txt` — PROD node, 137 reports, 2026-07-30 to 2026-08-14
- `TT CSP.txt` — UAT, 133 reports, 2026-05-29 to 2026-08-03

Related app docs:

- [csp-apache.conf.md](./csp-apache.conf.md) — Apache header snippets to deploy
- [csp-report-review-2026-08-03.md](./csp-report-review-2026-08-03.md) — earlier PROD review

---

## Verdict

CSP is still **Report-Only** (`disposition: report`) — nothing is blocking users
yet. There is **one real PNSPS SPA problem** (proof PDF preview `frame-src`).
Everything else is browser-extension noise or a **different app** on the same
UAT host.

The 2026-08-03 recommendation to add `frame-src` is **still not on the live
header**.

---

## Add / remove summary

**PROD — add one line, remove nothing:**

```apache
frame-src 'self' data: blob:;
```

Keep `script-src 'self'`. Do not add `'unsafe-inline'` or `'unsafe-eval'`.

**UAT — add the same line, remove nothing now:**

```apache
frame-src 'self' data: blob:;
```

Keep `script-src 'self' 'unsafe-inline' 'unsafe-eval'` for now (JSF payment recon
on the same host). Do not copy this `script-src` to PROD.

**Do not add on either env:** `'wasm-unsafe-eval'`, Youdao, NetEase CDN,
`todesktop-internal`, Google Fonts.

**Optional later (not required for these reports):** UAT can drop
`'unsafe-inline' 'unsafe-eval'` from the SPA header only after
`/paymentrecon-dept_web/` has its own CSP.

---

## Confirmed current PROD policy (Report-Only)

This is the live header that generated the P1/P2 reports. It matches the
`original-policy` in every PROD violation.

```apache
Header always set Content-Security-Policy-Report-Only "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"
```

Gap vs the reports: **no `frame-src`**. Framing therefore falls back to
`default-src 'self'`, which is why proof PDF preview reports `frame-src` with
an empty `blocked-uri`.

---

## Confirmed current UAT policy (Report-Only)

```apache
Header always set Content-Security-Policy-Report-Only "default-src 'self'; \
base-uri 'self'; \
object-src 'none'; \
frame-ancestors 'none'; \
form-action 'self'; \
script-src 'self' 'unsafe-inline' 'unsafe-eval'; \
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://pnspsuat.gld.gov.hk/api/csp-report"
```

UAT vs PROD differences:

- UAT `script-src` is `'self' 'unsafe-inline' 'unsafe-eval'` — PROD is `'self'` only.
- Both still lack `frame-src`.
- TT report `original-policy` was older: `script-src 'self' 'unsafe-inline'`
**without** `'unsafe-eval'`. That is why TT logged 42 JSF `eval` hits. Those
should stop under the current UAT header.

Do **not** copy `'unsafe-inline'` or `'unsafe-eval'` onto PROD. The React SPA
does not need them. `'unsafe-eval'` is only there for the shared-host JSF
payment recon app.

---

## Real problem (PROD P1 + P2)

| Volume | Directive | Blocked | Pages |
|---:|---|---|---|
| 150 | `frame-src` | empty `""` | `/proof/create/{id}` |

Source is always `static/js/4608.4af455e6.chunk.js`. Cause is proof file preview
in `src/pages/Proof/Create_FromApp/UploadFileTable.js`:
`FileReader.readAsDataURL` then `document.write` an `<iframe src="data:...">`.
With no `frame-src`, CSP uses `default-src 'self'` and blocks `data:` frames.
Browsers strip the `data:` URI from reports (empty `blocked-uri`).

**If this policy is promoted to enforcing without `frame-src`, PDF preview on
proof create will break.**

Apache fix (already documented in [csp-apache.conf.md](./csp-apache.conf.md),
not deployed):

```apache
frame-src 'self' data: blob:;
```

Optional frontend follow-up: switch preview to `URL.createObjectURL` + `blob:`
(still needs `frame-src ... blob:`).

Optional (low priority): `media-src 'self' blob: data:;` — current `blob:`
already covers captcha audio.

---

## Not a PNSPS SPA problem — do not allowlist

| Volume | Where | Directive | Blocked | Why ignore |
|---:|---|---|---|---|
| 109 | PROD | `script-src` | `wasm-eval` | `source-file: chrome-extension` |
| 18 | PROD | `media-src` | `dict.youdao.com` | Youdao translation plugin |
| 11 | PROD | `img-src` | `ydlunacommon-cdn.nosdn.127.net` | Youdao/NetEase CDN icons |
| 3 | PROD P2 | `script-src-elem` | `todesktop-internal` | Desktop wrapper |
| 105 | PROD 14 + UAT 91 | `img-src` | `www.w3.org/WAI/wcag2AA` | Already allowed in policy; mostly SPA `status-code: 404` noise. Badge is in `src/components/cards/AuthFooter.js`. |

Do **not** add `'unsafe-eval'`, `'wasm-unsafe-eval'`, Youdao, NetEase, or
`todesktop-internal` to the SPA policy.

---

## UAT-only: payment recon JSF (not the React app)

42 TT reports: `script-src` / `eval` on:

- `/paymentrecon-dept_web/report/paymentReconRpt01Search.jsf` (38)
- `/paymentrecon-dept_web/report/paymentReconRpt02Search.jsf` (3)
- `/paymentrecon-dept_web/manualrecon/manualReconSearch.jsf` (1)

This is a **separate JSF app** on the same Apache host. The TT logs were
generated under the **old** UAT policy (`script-src 'self' 'unsafe-inline'`).
Current UAT already adds `'unsafe-eval'`, so those `eval` reports should
disappear.

That UAT looseness is a workaround for JSF, not a requirement of PNSPS. Before
enforcing CSP:

- Keep PROD at `script-src 'self'` (do not add `'unsafe-eval'`).
- Prefer a path-specific header for `/paymentrecon-dept_web/` on UAT so the SPA
can later drop `'unsafe-inline'` / `'unsafe-eval'`.

---

## Recommended actions (ops / Apache, not app code)

1. Add `frame-src 'self' data: blob:;` to both PROD and UAT Report-Only headers.
Do not change PROD `script-src 'self'`.
2. Confirm proof-create preview reports drop after that deploy.
3. Keep Report-Only until `frame-src` volume is gone; remaining extension noise
is expected.
4. Do not promote UAT's `'unsafe-inline' 'unsafe-eval'` to PROD. Those tokens
exist for JSF payment recon on the shared UAT host.
5. Optional: give `/paymentrecon-dept_web/` its own Apache CSP so UAT SPA can
later match PROD (`script-src 'self'`).
6. Optional later: host the WCAG badge locally to cut `img-src` noise; change
preview to `blob:` URLs.

No application code change is required for the reports to become clean after
the Apache `frame-src` deploy.

---

## Backend reference

- Report endpoint: `POST /csp-report` (context path → `/api/csp-report`)
- Spring Security also sets a short API CSP on API responses
(`default-src 'self'; script-src 'self'; frame-ancestors 'self'`).
Frontend/Apache CSP above is what browsers enforce for the SPA document.

Laden…
Annuleren
Opslaan