Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

6.3 KiB

CSP Report Review (PROD, 2026-09-22)

Review of Content-Security-Policy-Report-Only violations from PNSPS PROD (https://pnsps.gld.gov.hk).

Source logs (external):

  • All_CSP.txt — 196 reports, 2026-08-27 to 2026-09-17

Related app docs:


Verdict

No app-side CSP concern in this dump. Almost every line is a browser extension, not PNSPS code. /proof/reply/{id} is just a busy authenticated page, so the same extension noise shows up there a lot.

CSP is still Report-Only (disposition: report) — the browser logged these hits and did not block the page.

The 2026-08-14 app-owned issue (proof PDF preview frame-src) is gone from this dump. Live PROD now includes frame-src 'self' data: blob:;.


Add / remove summary

PROD — add nothing required. Remove nothing.

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

Optional (low priority, already in csp-apache.conf.md):

media-src 'self' blob: data:;

Live PROD is still media-src 'self' blob: (no data:). This dump has only 2 matching hits in three weeks.

Do not add: 'wasm-unsafe-eval', Perplexity CDN, Youdao, NetEase CDN, Google Fonts.


Confirmed current PROD policy (Report-Only)

This is the live header that generated every report in All_CSP.txt. It matches original-policy in all 196 violations.

Header always set Content-Security-Policy-Report-Only "default-src 'self'; \
	base-uri 'self'; \
	object-src 'none'; \
	frame-ancestors 'none'; \
	frame-src 'self' data: blob:; \
	form-action 'self'; \
	script-src 'self'; \
	style-src 'self' 'unsafe-inline'; \
	style-src-elem 'self' 'unsafe-inline'; \
	img-src 'self' data:; \
	media-src 'self' blob:; \
	font-src 'self' data:; \
	connect-src 'self'; \
	upgrade-insecure-requests; \
	report-uri https://pnsps.gld.gov.hk/api/csp-report"

Changes vs the 2026-08-14 live header:

  • frame-src 'self' data: blob:; is now present.
  • img-src no longer allowlists https://www.w3.org / https://w3.org (badge is hosted locally).

style-src 'unsafe-inline' is expected for MUI and is the only real policy weakness. These reports do not show a new XSS issue.


Summary of findings

Count Directive Blocked Verdict
192 script-src wasm-eval Noise — Chrome extension
2 media-src data Optional leftover — data: not in live media-src
1 font-src frontend-cdn.perplexity.aiFKGroteskNeue.woff2 Noise — Perplexity sidebar
1 img-src ydlunacommon-cdn.nosdn.127.net.svg Noise — Youdao / NetEase plugin

No frame-src reports. No app eval. No Google Fonts.


Why wasm-eval volume is high

192 of 196 reports (98%) are script-src / wasm-eval.

Count source-file Notes
103 chrome-extension Every one with a location is line 23, column 39316 — the same injected script
89 (none) Chrome often sends a second report for the same violation without source-file

About 46 timestamps have 2+ reports in the same second (paired duplicates). That is why the log looks twice as large as the number of real events.

Password managers, translators, Grammarly-style tools, and similar extensions compile WebAssembly into the page. script-src 'self' (without 'wasm-unsafe-eval') reports that. Do not loosen script-src to silence it.

If quieter logs are needed, filter blocked-uri=wasm-eval plus source-file=chrome-extension (and the paired empty-source twin).


Why many /proof/reply reports

Count Page group
90 /login
38 /proof/reply/{id}
23 /publicNotice/{id}
15 /publicNotice/apply
10 /publicNotice
10 /proof/search
4 /paymentPage/*
3 /user/changePassword
2 /registerFromOrganization
1 /verify/*

The 38 Reply Proof hits span 12 proof IDs (29518, 29948, 30112, 30114, 30134, 30166, 30190, 30266, 30306, 30326, 30484, 30958). They are the same wasm-eval + Chrome extension pattern as login, apply, and notice detail.

Reply Proof is a long, authenticated screen. Anyone with a WASM extension triggers a report on every visit. No Reply Proof code change is required.


Not a PNSPS SPA problem — do not allowlist

Count Page Directive Blocked Why ignore
192 many (login 90, reply 38, …) script-src wasm-eval chrome-extension (line 23, col 39316) or paired empty source
1 /login font-src Perplexity FKGroteskNeue.woff2 Sidebar / extension
1 /login img-src NetEase ydlunacommon-cdn.nosdn.127.net Youdao-style translator
2 /publicNotice/apply, /proof/reply/30166 media-src data Optional data: gap only; 2 hits in three weeks

status-code: 404 on 166 reports is typical SPA client-route noise, not a broken document.


Optional: media-src and data:

Live policy: media-src 'self' blob:;

Captcha audio already uses blob: (CustomFormWizard.js and similar). Adding data: is low risk and already documented:

media-src 'self' blob: data:;

Not required for this dump.


  1. No Apache change required for these reports. frame-src deploy from 2026-08-14 looks effective (zero frame-src hits here).
  2. Keep PROD at script-src 'self'. Do not add 'unsafe-eval' or 'wasm-unsafe-eval'.
  3. Optional: add data: to media-src to match csp-apache.conf.md.
  4. Keep Report-Only until remaining volume is understood as extension noise; then promote the same policy to enforcing.
  5. Optional log hygiene: drop or sample wasm-eval + chrome-extension so real app regressions stay visible.

No application code change is required.


Backend reference

  • Report endpoint: POST /csp-report (context path → /api/csp-report)
  • Controller: CspReportController in PNSPS-backend
  • Frontend/Apache CSP above is what browsers apply to the SPA document