Skip to content

Security: Harden CSP by removing unsafe-inline and unsafe-eval (#325)#500

Merged
filthyrake merged 2 commits intodevfrom
feature/325-csp-security-hardening
Jan 4, 2026
Merged

Security: Harden CSP by removing unsafe-inline and unsafe-eval (#325)#500
filthyrake merged 2 commits intodevfrom
feature/325-csp-security-hardening

Conversation

@filthyrake
Copy link
Copy Markdown
Owner

Summary

This PR addresses the security issue #325 by hardening the Content Security Policy (CSP) headers to remove 'unsafe-inline' and 'unsafe-eval' directives that were defeating XSS protection.

Changes

  • Remove unsafe CSP directives from all HTML files:

    • script-src 'self' (removed 'unsafe-inline' and 'unsafe-eval')
    • style-src 'self' (removed 'unsafe-inline')
  • Replace Alpine.js with CSP-compatible build:

    • Public pages: Added alpine.csp.min.js from @alpinejs/csp CDN
    • Admin panel: Switched npm dependency from alpinejs to @alpinejs/csp
  • Extract inline scripts to external files:

    • web/public/static/js/pages/home.js - Home page Alpine component
    • web/public/static/js/pages/category.js - Category page Alpine component
    • web/public/static/js/pages/tag.js - Tag page Alpine component
  • Move inline styles to external CSS:

    • Added [x-cloak] rule to web/public/static/css/bundle.css
    • Added [x-cloak] rule to web/admin/src/styles/tokens.css
  • TypeScript support:

    • Added type declaration file for @alpinejs/csp module

Security Impact

The CSP-compatible Alpine.js build avoids using eval() and Function() constructors, allowing stricter CSP headers that provide actual XSS protection. Previously, the 'unsafe-inline' and 'unsafe-eval' directives made the CSP essentially ineffective against XSS attacks.

Files Changed

File Change
web/public/index.html Updated CSP, removed inline script/style
web/public/category.html Updated CSP, removed inline script/style
web/public/tag.html Updated CSP, removed inline script/style
web/public/watch.html Updated CSP, removed inline style
web/admin/index.html Updated CSP, removed inline style
web/admin/package.json Changed alpine dependency to @alpinejs/csp
web/admin/src/main.ts Import from @alpinejs/csp
web/public/static/css/bundle.css Added x-cloak style
web/admin/src/styles/tokens.css Added x-cloak style
web/public/static/js/pages/home.js New - extracted from index.html
web/public/static/js/pages/category.js New - extracted from category.html
web/public/static/js/pages/tag.js New - extracted from tag.html
web/public/static/vendor/alpine.csp.min.js New - CSP-compatible Alpine build
web/admin/src/types/alpinejs-csp.d.ts New - TypeScript declaration

Test plan

  • Verify home page loads and displays videos correctly
  • Verify category page loads and displays videos
  • Verify tag page loads and displays videos
  • Verify watch page plays videos correctly
  • Verify admin panel loads and all functionality works
  • Verify no CSP errors appear in browser console
  • Verify mobile navigation works
  • Verify search functionality works on all pages

Closes #325

🤖 Generated with Claude Code

filthyrake and others added 2 commits January 4, 2026 06:24
- Remove 'unsafe-inline' and 'unsafe-eval' from script-src directives
- Remove 'unsafe-inline' from style-src directives
- Replace Alpine.js standard build with CSP-compatible build
  - Public pages: alpine.csp.min.js from @alpinejs/csp
  - Admin: npm package @alpinejs/csp instead of alpinejs
- Extract inline JavaScript to external files:
  - web/public/static/js/pages/home.js (from index.html)
  - web/public/static/js/pages/category.js (from category.html)
  - web/public/static/js/pages/tag.js (from tag.html)
- Move [x-cloak] CSS to external stylesheets:
  - web/public/static/css/bundle.css
  - web/admin/src/styles/tokens.css
- Add TypeScript declaration for @alpinejs/csp module

The CSP-compatible Alpine.js build avoids using eval() and Function()
constructors, enabling stricter Content Security Policy headers that
provide real XSS protection.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix global namespace pollution in page JS files:
  - Wrap all page components in IIFEs with 'use strict'
  - Register components via Alpine.data() instead of global functions
  - Encapsulate constants (MAX_SEARCH_LENGTH, SLUG_PATTERN) in IIFE scope

- Improve script loading consistency:
  - Add defer attribute to all page script tags
  - Remove parentheses from x-data attributes (use string reference)
  - Ensure consistent loading order across all pages

- Strengthen CSP headers:
  - Add object-src 'none' to block plugin-based XSS vectors
  - Add base-uri 'self' to prevent base tag injection attacks
  - Apply to all HTML files (index, category, tag, watch, admin)

- Document vendor file provenance:
  - Add source URL, version, license info to alpine.csp.min.js
  - Include instructions for verifying integrity

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@filthyrake filthyrake merged commit 86dfc1b into dev Jan 4, 2026
3 of 4 checks passed
@filthyrake filthyrake deleted the feature/325-csp-security-hardening branch January 4, 2026 14:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Security: CSP allows unsafe-inline and unsafe-eval defeating XSS protection

1 participant