Changeset f7d142f in Klonkt for src/server.js


Ignore:
Timestamp:
06/28/2026 03:36:22 PM (2 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
81bb9c5
Parents:
127f87e
Message:

chore(csp): drop the last script unsafe-inline + add Permissions-Policy

Move every inline on* handler to a shared delegated data-* handler, so script-src-attr
can be 'none' instead of 'unsafe-inline'. Add a Permissions-Policy header disabling
camera/microphone/geolocation/Topics (embed features left at default).

  • views/shell.ejs — shared delegated submit/change/click/error handler (data-confirm, data-autosubmit, data-lang-switch, data-selectall, data-back, data-fallback)
  • views/{pages,partials}/*.ejs — 18 inline on* handlers -> data-* attributes (14 files)
  • server.js — scriptSrcAttr 'unsafe-inline' -> 'none'; Permissions-Policy header
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/server.js

    r127f87e rf7d142f  
    109109        (req, res) => `'nonce-${res.locals.cspNonce}'`,
    110110      ],
    111       // Helmet's default sets script-src-attr to 'none', which blocks ALL inline
    112       // event handlers (onchange/onclick/onsubmit) — causing e.g. the avatar
    113       // upload (<input onchange="this.form.submit()">) and the role dropdown to
    114       // silently do nothing. We explicitly allow inline handlers, consistent with
    115       // the already-allowed inline <script> above.
    116       scriptSrcAttr: ["'unsafe-inline'"],
     111      // No inline event handlers anywhere: every on* attribute was moved to a
     112      // delegated data-* handler (the shared script in shell.ejs), so inline
     113      // handlers are blocked entirely — this closes the last 'unsafe-inline' in
     114      // the script directives.
     115      scriptSrcAttr: ["'none'"],
    117116      styleSrc: ["'self'", "'unsafe-inline'"],
    118117      // blob: required for the image editor (Cropper) — it displays the chosen
     
    144143  referrerPolicy: { policy: 'strict-origin-when-cross-origin' },
    145144}));
     145
     146// Permissions-Policy: disable powerful features Klonkt never uses (camera, microphone,
     147// geolocation) and opt out of the Topics API. Features that embeds legitimately need
     148// (autoplay, fullscreen, encrypted-media, picture-in-picture) are left at their default
     149// allowlist, so YouTube/Spotify/SoundCloud players keep working.
     150app.use((req, res, next) => {
     151  res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=(), browsing-topics=()');
     152  next();
     153});
    146154
    147155app.set('view engine', 'ejs');
Note: See TracChangeset for help on using the changeset viewer.