Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

csp-report-review-2026-08-03.md 5.2 KiB

1 месяц назад
​
​
​
​
​
​
​
​
​
​
​
​
​
1 месяц назад
5 дней назад
1 месяц назад
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. # CSP Report Review (PROD, 2026-08-03)
  2. Review of Content-Security-Policy-Report-Only violations from PNSPS PROD
  3. (`https://pnsps.gld.gov.hk`), for deciding Apache CSP updates.
  4. Source logs (external):
  5. - `PNSPS PROD CSP Report 2026-08-03.txt`
  6. - `summary.txt`
  7. - `CSP Issue 1.txt` (`script-src` / `eval` samples)
  8. Related app docs:
  9. - [csp-apache.conf.md](./csp-apache.conf.md) — Apache header snippets to deploy
  10. - [csp-report-review-2026-08-14.md](./csp-report-review-2026-08-14.md) — later PROD + UAT review (add/remove summary)
  11. - [csp-report-review-2026-09-22.md](./csp-report-review-2026-09-22.md) — later PROD review (`All_CSP.txt`)
  12. ---
  13. ## Policy in effect at report time
  14. ```
  15. default-src 'self';
  16. base-uri 'self';
  17. object-src 'none';
  18. frame-ancestors 'none';
  19. form-action 'self';
  20. script-src 'self';
  21. style-src 'self' 'unsafe-inline';
  22. style-src-elem 'self' 'unsafe-inline';
  23. img-src 'self' data: https://www.w3.org https://w3.org;
  24. media-src 'self' blob:;
  25. font-src 'self' data:;
  26. connect-src 'self';
  27. upgrade-insecure-requests;
  28. report-uri https://pnsps.gld.gov.hk/api/csp-report
  29. ```
  30. Notes:
  31. - Disposition was `report` (Report-Only); nothing was enforced.
  32. - No `frame-src` → framing falls back to `default-src 'self'`.
  33. ---
  34. ## Summary of findings
  35. Most reports are **browser / extension noise**. Only one directive change is
  36. required for **app functionality**: add `frame-src`.
  37. | Approx. volume | Directive | Blocked | Verdict |
  38. |---:|---|---|---|
  39. | ~3000 | `frame-src` | empty / `data:` (URI often stripped) | **App** — PDF preview iframes |
  40. | ~1500 | `script-src` | `wasm-eval` | Noise — `chrome-extension` |
  41. | ~1400 | `font-src` | `fonts.gstatic.com` (Inter / Nunito) | Noise — not app fonts |
  42. | ~500 | `img-src` | `https://www.w3.org/WAI/wcag2AA` | Already allowed; mostly doc `404` noise |
  43. | ~240 | `font-src` | `at.alicdn.com`, `cdn.yiban.io`, Perplexity CDN | Noise — toolbars / extensions |
  44. | ~180 | `style-src-elem` | `fonts.googleapis.com` | Noise — not loaded by app |
  45. | ~70 | `script-src` | `eval` (line ~67) | Noise — no app `eval` |
  46. | rest | various | Kaspersky, Youdao, Quark, `todesktop-internal`, etc. | Noise |
  47. App fonts are self-hosted (`@fontsource` Public Sans / Noto; see `public/index.html`
  48. and `src/assets/fonts.css`). Google Fonts (Roboto / Inter / Nunito) are **not**
  49. part of the app and must not be allowlisted.
  50. ---
  51. ## App-owned issue: `frame-src`
  52. ### Cause
  53. Proof upload preview in
  54. `src/pages/Proof/Create_FromApp/UploadFileTable.js`:
  55. 1. `FileReader.readAsDataURL(...)` builds a `data:` URL
  56. 2. `window.open("")` then `document.write` an `<iframe src="data:...">`
  57. With no `frame-src`, CSP uses `default-src 'self'`, which blocks `data:` frames.
  58. Browsers often report `blocked-uri` as empty (`""`) for privacy.
  59. Almost all of these hits are on `/proof/create/...`, source
  60. `static/js/4608.*.chunk.js`.
  61. ### Apache fix
  62. ```apache
  63. frame-src 'self' data: blob:;
  64. ```
  65. ### Optional follow-up (frontend)
  66. Prefer `URL.createObjectURL` + `blob:` for preview (still needs `frame-src ... blob:`).
  67. ---
  68. ## Optional: `media-src` and `data:`
  69. Small volume of `media-src` / `data` on login and related pages.
  70. Captcha audio already uses `blob:` (`CustomFormWizard.js` and similar). Adding
  71. `data:` is low risk:
  72. ```apache
  73. media-src 'self' blob: data:;
  74. ```
  75. ---
  76. ## Already covered / not a CSP gap
  77. ### WCAG badge (`img-src` / `www.w3.org`)
  78. `AuthFooter.js` loads `https://www.w3.org/WAI/wcag2AA`. Policy already allows
  79. `https://www.w3.org` and `https://w3.org`. Many reports had document
  80. `status-code: 404` (SPA shell). No Apache change required.
  81. Optional hardening: host the badge image locally.
  82. ### Payment gateway CSS (`epaygateway1.gcis.gov.hk`)
  83. Single `style-src-elem` hit on `/paymentPage/callback` with gateway referrer.
  84. Card payment uses `window.location.assign(redirecturl)`, not embedded gateway CSS.
  85. Do **not** allowlist unless a real UI break is confirmed.
  86. ---
  87. ## Do not add to CSP
  88. | Requested by reports | Why not |
  89. |---|---|
  90. | `'unsafe-eval'` / `'wasm-unsafe-eval'` | Extension / injected; app has no `eval` |
  91. | `fonts.googleapis.com` / `fonts.gstatic.com` | App uses self-hosted fonts |
  92. | Kaspersky (`*.kis.v2.scr.kaspersky-labs.com`) | AV injection |
  93. | Perplexity, Youdao, Quark, alicdn, yiban, NetEase CDN | Third-party client tooling |
  94. | `todesktop-internal` | Desktop wrapper noise |
  95. | `epaygateway1.gcis.gov.hk` (styles) | Not required for current payment flow |
  96. ---
  97. ## Recommended Apache policy
  98. Use the snippets in [csp-apache.conf.md](./csp-apache.conf.md).
  99. Changes vs the 2026-08-03 deployed policy:
  100. 1. Add `frame-src 'self' data: blob:;`
  101. 2. Change `media-src` to `'self' blob: data:;`
  102. ### Rollout
  103. 1. Deploy updated **Report-Only** header.
  104. 2. Watch `/api/csp-report` for a few days — expect `frame-src` volume to drop;
  105. remaining extension noise is OK.
  106. 3. Promote the same policy to **enforcing** when app-owned directives look clean.
  107. Adjust `report-uri` host for UAT vs PROD:
  108. - UAT: `https://pnspsuat.gld.gov.hk/api/csp-report`
  109. - PROD: `https://pnsps.gld.gov.hk/api/csp-report`
  110. ---
  111. ## Backend reference
  112. - Report endpoint: `POST /csp-report` (context path → `/api/csp-report`)
  113. - Spring Security also sets a short API CSP on API responses
  114. (`default-src 'self'; script-src 'self'; frame-ancestors 'self'`).
  115. Frontend/Apache CSP above is what browsers enforce for the SPA document.