Skip to content

feat: Implement Subresource Integrity (SRI) for CDN resources#2902

Open
suciu-daniel wants to merge 8 commits intomainfrom
issue-2558-sri-implementation
Open

feat: Implement Subresource Integrity (SRI) for CDN resources#2902
suciu-daniel wants to merge 8 commits intomainfrom
issue-2558-sri-implementation

Conversation

@suciu-daniel
Copy link
Collaborator

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

  • Created scripts/generate-sri-hashes.py for SHA-384 hash generation
  • Created scripts/verify-sri-hashes.py for hash verification
  • Added load_sri_hashes() function in admin.py
  • Generated mcpgateway/sri_hashes.json with all resource hashes
  • Pinned all CDN library versions (Alpine.js, Chart.js, Marked, DOMPurify)

Phase 3: Template Updates

  • Added SRI to all 15 CDN resources in admin.html
  • Added SRI to Font Awesome in login.html
  • Added SRI to Font Awesome in change-password-required.html
  • All resources include integrity and crossorigin="anonymous" attributes

Phase 4: CI Integration

  • Updated make sri-verify to use verification script
  • Added SRI verification step to .github/workflows/full-build-pipeline.yml
  • CI fails build on hash mismatch

Phase 5: Documentation

  • Updated docs/docs/architecture/adr/014-security-headers-cors-middleware.md
  • Updated docs/docs/manage/securing.md
  • Documented CDN library update workflow

Protected Resources (15 total)

  • HTMX (1.9.10)
  • Alpine.js (3.14.1)
  • Chart.js (4.4.1)
  • Marked (11.1.1)
  • DOMPurify (3.0.6)
  • CodeMirror core + 6 modes/themes (5.65.18)
  • Font Awesome (6.4.0)

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

- 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>
@suciu-daniel suciu-daniel self-assigned this Feb 13, 2026
@suciu-daniel suciu-daniel added the security Improves security label Feb 13, 2026
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>
Copy link
Member

@crivetimihai crivetimihai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

security Improves security

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[EPIC][SECURITY]: Subresource Integrity (SRI) for external CDN resources

2 participants