logto icon indicating copy to clipboard operation
logto copied to clipboard

fix(security): add per-request CSP nonce and inject into served index to fix #7456

Open venkatprasadh opened this issue 5 months ago • 2 comments

Summary 📝

Add per-request CSP nonce support and automatic nonce injection for served SPA index.html so inline boot scripts are allowed without relaxing the Content Security Policy (CSP).


Files Changed 📂

  • koa-security-headers.ts
    • Generate a per-request base64 nonce (crypto.randomBytes).
    • Expose nonce on ctx.state.cspNonce.
    • Inject 'nonce-<value>' into the script-src directive for console and experience Helmet CSP settings.
  • koa-serve-static.ts
    • When serving SPA index.html, inject nonce="..." into inline <script> tags that lack src/nonce so the markup matches the CSP header.

Notes / Disclaimers ⚠️

  • The browser console may show: "Ignoring 'unsafe-inline' within script-src: nonce-source or hash-source specified" if 'unsafe-inline' remains in existing directives; this is expected — remove 'unsafe-inline' from the CSP for a stricter policy.
  • Middleware ordering is important: koa-security-headers must run before the static-serving middleware so ctx.state.cspNonce is available when index.html is patched.

Testing ✅

Manual run (local container / dev):

  1. Start server/container with the updated code.
  2. Request the console page and verify response header contains the nonce:
    • curl -v http://localhost:3001/console (inspect Content-Security-Policy header)
  3. Verify served HTML contains <script nonce="..."> for inline scripts:
    • curl http://localhost:3001/console | grep -i 'nonce='
  4. Open page in browser — confirm CSP inline-script blocked message is gone for allowed inline scripts.
  5. Verified middleware order: security middleware applied before static SPA middleware so nonce is injected.
  6. Confirmed behaviour with and without existing nonce attributes: only inline scripts without src/nonce are modified.

Checklist 📋

Item Status
.changeset (add entry describing this change)  
unit tests (consider adding tests that assert CSP header contains nonce and served index.html contains matching nonce)  
integration tests (optionally add an end-to-end test that fetches header and HTML and asserts match)  
necessary TSDoc comments (added minimal inline comments; expand if desired)  

If you want, I can prepare the .changeset file and a small integration test that fetches the page and asserts header/body nonce equality.

venkatprasadh avatar Nov 08 '25 11:11 venkatprasadh

COMPARE TO master

Total Size Diff :chart_with_upwards_trend: +2.54 KB

Diff by File
Name Diff
packages/core/src/middleware/koa-security-headers.ts :chart_with_upwards_trend: +1.66 KB
packages/core/src/middleware/koa-serve-static.ts :chart_with_upwards_trend: +900 Bytes

github-actions[bot] avatar Nov 08 '25 11:11 github-actions[bot]

Hi, can you please check the CI result and fix the lint issues?

wangsijie avatar Nov 15 '25 01:11 wangsijie

Can someone please fix this and get it merged ASAP @wangsijie it appears @venkatprasadh isn't coming back. I'm experiencing the same bug.

idcleartomwieland avatar Dec 16 '25 22:12 idcleartomwieland

I have fixed the linter errors/ @wangsijie could you please approve the workflow triggers to recheck the validations needed for PR merge?

venkatprasadh avatar Dec 17 '25 08:12 venkatprasadh