Repository navigation
Open
Labels
enhancementNew feature or requestNew feature or requestsecuritySecurity improvements and vulnerability fixesSecurity improvements and vulnerability fixes
Description
Background
PR #342 (issue #19) shipped Content-Security-Policy in Report-Only mode (src/index.ts:104, reportOnly: true), with a violation collector at /csp-report (src/index.ts:91). The policy is otherwise strict: scriptSrc: ['self', 'https://esm.sh'] with no 'unsafe-inline'.
CSP cannot be flipped to enforced yet because the views still contain inline JavaScript, which the policy would block. This issue tracks the refactor needed to enable enforcement.
Current inline-JS inventory (as of main @ 442365c)
- 24 inline
script.blocks across 23 view files - 46 inline
on*handler attributes (onclick,onchange,onsubmit, …) across 20 view files
Note:
styleSrcalready permits'unsafe-inline', so inline styles are fine — this is scoped to scripts only.
Files with inline script. blocks (24)
src/views/admin/approvalBonuses.pug
src/views/admin/approvalPanel.pug
src/views/admin/editApprovedSubmission.pug
src/views/admin/members.pug
src/views/admin/mergeSpeciesDialog.pug
src/views/admin/queue.pug
src/views/admin/speciesEdit.pug
src/views/admin/speciesList.pug
src/views/admin/waitingPeriod.pug
src/views/admin/witnessQueue.pug
src/views/bapForm/imageUpload.pug
src/views/demo/emails.pug
src/views/dialog/cares-fry-share.pug
src/views/dialog/cares-register.pug
src/views/dialog/collection-add.pug
src/views/dialog/collection-edit.pug
src/views/dialog/collection-link.pug
src/views/display.pug
src/views/member.pug
src/views/submission/editMedia.pug
src/views/submission/review.pug
src/views/submit.pug
src/views/test/tom-select-demo.pug
Files with inline on* handlers (46 across these 20)
src/views/account/links.pug
src/views/account/tankPresetForm.pug
src/views/account/tankPresets.pug
src/views/admin/addCommonNameForm.pug
src/views/admin/addScientificNameForm.pug
src/views/admin/canonicalRecommendations.pug
src/views/admin/editApprovedSubmission.pug
src/views/admin/speciesEdit.pug
src/views/admin/speciesList.pug
src/views/bapForm/imageUpload.pug
src/views/demo/emails.pug
src/views/dialog/cares-fry-share.pug
src/views/dialog/cares-register.pug
src/views/dialog/collection-edit.pug
src/views/mixins/collectionCard.pug
src/views/mixins/emptyState.pug
src/views/species/detail.pug
src/views/species/explorer.pug
src/views/submission/editMedia.pug
src/views/submission/review.pug
Approach
Two viable paths (pick one; not mutually exclusive):
- Externalize to static JS (preferred, aligns with HTMX-first architecture) — move inline
script.blocks intopublic/js/*files loaded with<script src>, and replaceon*attributes withaddEventListenerwired viadata-*hooks or HTMX attributes. No'unsafe-inline', no per-request nonce plumbing. - Per-request nonces — generate a nonce per response, add
nonce=to each allowed inline block, and setscriptSrc: ['self', 'https://esm.sh', (req,res)=>\'nonce-${res.locals.nonce}'`]`. Keeps code inline but requires threading the nonce through every template.
Given the CLAUDE.md rule to prefer HTMX over custom JS, option 1 is the better fit for most of these.
Definition of done
- No inline
script.blocks or < 6B16 code class="notranslate">on* handlers remain insrc/views(or all remaining ones carry a nonce) -
/csp-reportshows noscript-srcviolations during an E2E run - Flip
reportOnly: true→falseinsrc/index.ts - Verify all interactive flows still work (dialogs, admin panels, image upload, species explorer)
References
- CSP config:
src/index.ts:104-123 - Report collector:
src/index.ts:91-101 - Follow-up from Implement CSRF protection for state-mutating operations #19 / PR feat(security): full CSRF protection + session hardening — all 3 phases (#19) #342
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requestsecuritySecurity improvements and vulnerability fixesSecurity improvements and vulnerability fixes
Activity