feat: Implement Subresource Integrity (SRI) for CDN resources#2902
feat: Implement Subresource Integrity (SRI) for CDN resources#2902suciu-daniel wants to merge 8 commits intomainfrom
Conversation
- Add scripts/generate-sri-hashes.py to generate SHA-384 hashes for all CDN resources - Generate mcpgateway/sri_hashes.json with hashes for 15 CDN resources: * HTMX 1.9.10 * Alpine.js 3.14.1 (pinned from @3.x.x) * Chart.js 4.4.1 (pinned from latest) * Marked 11.1.1 (newly added) * DOMPurify 3.0.6 (newly added) * CodeMirror 5.65.18 (7 files) * Font Awesome 6.4.0 - Update scripts/download-cdn-assets.sh to download marked and dompurify - Add Makefile targets: make sri-generate and make sri-verify - Pin all CDN versions to exact semver for reproducibility Addresses Phase 1 (Version Pinning) and Phase 2 (Hash Generation) of issue #2558 Related to #2558 Signed-off-by: SuciuDaniel <Daniel.Vasile.Suciu@ibm.com>
- Add integrity and crossorigin attributes to all CDN resources - Pin Alpine.js to 3.14.1 (was using @3.x.x) - Pin Chart.js to 4.4.1 (was using latest) - Pin Marked to 11.1.1 (was using latest) - Pin DOMPurify to 3.0.6 (was using latest) - Add SRI to all 7 CodeMirror JS files - Add SRI to 2 CodeMirror CSS files - Add SRI to Font Awesome CSS All SRI hashes loaded from sri_hashes.json via load_sri_hashes() function. Changes only apply in CDN mode (ui_airgapped=false). Closes #2558 (Phase 3) Signed-off-by: SuciuDaniel <Daniel.Vasile.Suciu@ibm.com>
- Create scripts/verify-sri-hashes.py to verify CDN content matches stored hashes - Update Makefile sri-verify target to use new verification script - Add SRI verification step to full-build-pipeline.yml CI workflow - Verification fetches each CDN URL and compares SHA-384 hash - Fails CI build if any hash mismatch detected - Provides clear error messages for debugging The verification script: - Fetches all 15 CDN resources - Calculates SHA-384 hashes - Compares against mcpgateway/sri_hashes.json - Reports mismatches with expected vs actual hashes - Detects missing or extra hashes in config Closes #2558 (Phase 4) Signed-off-by: SuciuDaniel <Daniel.Vasile.Suciu@ibm.com>
Phase 1: Add load_sri_hashes() function to admin.py - Load SRI hashes from mcpgateway/sri_hashes.json - Cache hashes in memory for performance - Pass sri_hashes to all template contexts (admin, login, change-password) Phase 2: Update login.html and change-password-required.html - Add SRI integrity attributes to Font Awesome CSS - Add crossorigin="anonymous" for CORS compliance - Use sri_hashes.fontawesome from template context Additional: Clean up generate-sri-hashes.py formatting - Add UTF-8 encoding declaration - Fix trailing whitespace and newlines - Improve code consistency Related to #2558 Signed-off-by: SuciuDaniel <Daniel.Vasile.Suciu@ibm.com>
Update ADR-0014 (Security Headers): - Add comprehensive SRI implementation section - Document all 15 protected CDN resources - Explain security benefits and usage - Include CDN library update workflow - Mark SRI as implemented in version 1.0.0 Update securing.md (Security Guide): - Add SRI subsection under Network Security - Document protected resources and verification commands - Provide step-by-step CDN library update workflow - Add security checklist for SRI compliance - Explain threats mitigated (CDN compromise, MITM, DNS hijacking) The documentation provides: - Clear usage instructions for make sri-generate and sri-verify - Step-by-step guide for updating CDN library versions - Security benefits and threat mitigation details - Integration with CI pipeline verification Closes #2558 (Phase 5) Signed-off-by: SuciuDaniel <Daniel.Vasile.Suciu@ibm.com>
Add recursive-include rule for *.json files in mcpgateway/ directory to ensure sri_hashes.json is included in source distributions. Fixes check-manifest warning about missing mcpgateway/sri_hashes.json Signed-off-by: SuciuDaniel <Daniel.Vasile.Suciu@ibm.com>
- Remove trailing whitespace in template files - Add missing newlines at end of Python scripts - Fix indentation in HTML script/link tags Signed-off-by: SuciuDaniel <Daniel.Vasile.Suciu@ibm.com>
crivetimihai
left a comment
There was a problem hiding this comment.
Thanks for this solid SRI implementation, @suciu-daniel. The CI verification pipeline and centralized hash storage are well-designed. A few items:
Bug — Invalid HTML in login.html (lines 509-514 of diff)
The Font Awesome <link> tag has a broken closing. crossorigin="anonymous"> closes the tag, then /> becomes stray literal text in the page output. Compare with the correct form in change-password-required.html and admin.html. Fix: remove the extra > and close with just />.
URL mismatch for HTMX between template and hash generator
admin.html uses src="https://unpkg.com/htmx.org@1.9.10" but generate-sri-hashes.py hashes https://unpkg.com/htmx.org@1.9.10/dist/htmx.min.js. The short URL 302-redirects. Browsers compute SRI against the final response body so it may work, but this is fragile. Recommend aligning the template src to the canonical /dist/htmx.min.js path.
CDN_RESOURCES duplicated across two scripts
generate-sri-hashes.py and verify-sri-hashes.py maintain identical CDN_RESOURCES dicts. Extract to a shared module to prevent drift.
Tailwind CSS excluded but undocumented in templates
All three templates load Tailwind from CDN without SRI. The generate script has a comment explaining the JIT exclusion, but the templates have no comment. A brief <!-- No SRI: Tailwind JIT --> in each template would help maintainability.
- Fix invalid HTML in login.html (broken closing tag on Font Awesome link) - Fix HTMX URL mismatch (use canonical /dist/htmx.min.js path) - Extract CDN_RESOURCES to shared scripts/cdn_resources.py module - Add Tailwind JIT exclusion comments to all three templates - Regenerate SRI hashes with corrected HTMX URL Closes feedback items from PR #2902 review Signed-off-by: SuciuDaniel <Daniel.Vasile.Suciu@ibm.com>
Summary
Implements complete Subresource Integrity (SRI) protection for all external CDN resources to cryptographically verify that fetched resources have not been tampered with.
Changes
Phase 1 & 2: Infrastructure
scripts/generate-sri-hashes.pyfor SHA-384 hash generationscripts/verify-sri-hashes.pyfor hash verificationload_sri_hashes()function inadmin.pymcpgateway/sri_hashes.jsonwith all resource hashesPhase 3: Template Updates
admin.htmllogin.htmlchange-password-required.htmlintegrityandcrossorigin="anonymous"attributesPhase 4: CI Integration
make sri-verifyto use verification script.github/workflows/full-build-pipeline.ymlPhase 5: Documentation
docs/docs/architecture/adr/014-security-headers-cors-middleware.mddocs/docs/manage/securing.mdProtected Resources (15 total)
Security Benefits
✅ CDN Compromise Protection - Malicious code blocked
✅ MITM Attack Prevention - Tampered content detected
✅ DNS Hijacking Defense - Redirected content rejected
✅ Version Drift Detection - CI catches unexpected changes
✅ Automated Verification - Every build validates hashes
Testing
$ make sri-verify 🔐 Verifying SRI hashes against CDN content... Verifying htmx... ✓ Verifying alpinejs... ✓ Verifying chartjs... ✓ Verifying marked... ✓ Verifying dompurify... ✓ Verifying codemirror_js... ✓ Verifying codemirror_addon_simple... ✓ Verifying codemirror_mode_javascript... ✓ Verifying codemirror_mode_python... ✓ Verifying codemirror_mode_shell... ✓ Verifying codemirror_mode_go... ✓ Verifying codemirror_mode_rust... ✓ Verifying codemirror_css... ✓ Verifying codemirror_theme_monokai... ✓ Verifying fontawesome... ✓ ✅ All 15 SRI hashes verified successfully!Closes #2558