Changeset e685f55 in Klonkt


Ignore:
Timestamp:
07/21/2026 01:54:46 AM (7 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
603d246
Parents:
d48ea02
git-author:
Robin <roboburr@…> (07/21/2026 01:54:23 AM)
git-committer:
Robin <roboburr@…> (07/21/2026 01:54:46 AM)
Message:

Fix: paid client scripts were blocked by CSP (garbage nonce)

The paid-* views wrote nonce="<%= cspNonce %>" on their <script> tags, but
cspNonce is not a real value in the template: renderPage's default is a
function, so it rendered as nonce="() =&gt; ". injectCspNonce only adds
the real nonce to <script> tags that have NO nonce attribute yet, so these
tags kept the garbage nonce. Under our strict-dynamic CSP (no unsafe-inline,
no host sources, 'self' ignored) that blocked every one of them:

  • the vendored SimpleWebAuthnBrowser lib never loaded
  • the passkey-creation script (slice 3) never ran
  • the per-post unlock script (slice 4) never ran
  • the paid-price toggle in the editor (slice 2) never ran

Tests never caught it: the WebAuthn ceremony only runs in a real browser,
so nothing exercised these inline scripts. The convention everywhere else
is a plain <script> with no nonce; injectCspNonce fills in the real one.
Drop the hand-written nonce attribute so that happens.

Changed files:
src/views/pages/paid-gate.ejs

  • drop nonce attr on the vendored lib + unlock scripts

src/views/pages/paid-passkey.ejs

  • drop nonce attr on the vendored lib + registration scripts

src/views/pages/post-edit.ejs

  • drop nonce attr on the paid-price toggle script

-robo
Co-Authored-By: Claude Opus 4.8 <noreply@…>

Location:
src/views/pages
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/views/pages/paid-gate.ejs

    rd48ea02 re685f55  
    2323</article>
    2424
    25 <script src="/assets/vendor/simplewebauthn-browser.umd.min.js" nonce="<%= cspNonce %>"></script>
    26 <script nonce="<%= cspNonce %>">
     25<script src="/assets/vendor/simplewebauthn-browser.umd.min.js"></script>
     26<script>
    2727(function () {
    2828  var base = "<%= (typeof siteUrlBase !== 'undefined' && siteUrlBase ? siteUrlBase : '') %>";
  • src/views/pages/paid-passkey.ejs

    rd48ea02 re685f55  
    1212</section>
    1313
    14 <script src="/assets/vendor/simplewebauthn-browser.umd.min.js" nonce="<%= cspNonce %>"></script>
    15 <script nonce="<%= cspNonce %>">
     14<script src="/assets/vendor/simplewebauthn-browser.umd.min.js"></script>
     15<script>
    1616(function () {
    1717  var options = <%- optionsJson %>;
  • src/views/pages/post-edit.ejs

    rd48ea02 re685f55  
    377377            </label>
    378378          </div>
    379           <script nonce="<%= cspNonce %>">
     379          <script>
    380380            (function(){ var p=document.getElementById('pe-paid'), box=document.getElementById('pe-paid-price');
    381381              if (p&&box&&!p.__wired){ p.__wired=true; p.addEventListener('change', function(){ box.style.display=p.checked?'':'none'; }); } })();
Note: See TracChangeset for help on using the changeset viewer.