fix: pin CDN scripts + theme CSS with SRI integrity hashes (closes #19)#20
fix: pin CDN scripts + theme CSS with SRI integrity hashes (closes #19)#20
Conversation
The dashboard loads three cross-origin assets without integrity
attributes:
highlight.js/11.9.0/styles/vs2015.min.css
highlight.js/11.9.0/highlight.min.js
marked/12.0.1/marked.min.js
Marked.js parses raw markdown and highlight.js runs on every code
block — a swapped CDN payload would execute in our origin with full
DOM access. Subresource Integrity (sha512 hash + crossorigin="anonymous")
makes the browser refuse anything whose hash does not match a
known-good value.
Wrinkle: static/js/app.js used to swap `hljsLink.href` between the
dark (vs2015) and light (github) stylesheets at runtime via a plain
ternary. Adding integrity to the static <link> tag would have made
the runtime swap break — the browser reads the (now-stale) integrity
at fetch time and refuses the new sheet.
Fix: introduced HLJS_THEME_SHEETS const map keyed by theme name,
each entry carrying { href, integrity }. New applyHljsTheme(theme)
helper sets integrity FIRST then href so the browser sees the right
hash when it triggers the new fetch. Both inline ternary call sites
(applyTheme and setWorkspaceMode) now call the helper instead of
duplicating the logic.
All four SHA-512 hashes verified two ways:
1. cdnjs SRI API
gh api 'https://api.cdnjs.com/libraries/<name>/<version>?fields=sri'
2. Re-derived from actual CDN content
curl -sL <url> | openssl dgst -sha512 -binary | base64
→ all four match.
pytest 75/75 OK (no behaviour change in Python code).
Live HTTP smoke: served HTML carries integrity + crossorigin on all
three tags; manual browser verification path documented in PR body.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe pull request adds Subresource Integrity (SRI) support to CDN-loaded Highlight.js and Marked.js assets by appending ChangesSRI Pinning and Theme-Aware Asset Loading
Sequence DiagramsequenceDiagram
participant User
participant App as app.js
participant DOM
participant Browser
participant CDN
rect rgb(240, 100, 100, 0.5)
Note over User,CDN: OLD: Theme Swap (SRI Mismatch Risk)
User->>App: Change theme to 'light'
App->>DOM: hljsLink.href = github.min.css URL
Note over DOM: integrity still = vs2015 hash
DOM->>Browser: Request stylesheet
Browser->>CDN: Fetch github.min.css
CDN-->>Browser: CSS file
Browser->>Browser: Hash mismatch!<br/>Reject stylesheet ✗
end
rect rgb(100, 200, 100, 0.5)
Note over User,CDN: NEW: Theme Swap (SRI Valid)
User->>App: Change theme to 'light'
App->>App: Look up HLJS_THEME_SHEETS['light']
App->>DOM: applyHljsTheme('light')
Note over DOM: Sets integrity = github hash
Note over DOM: Then sets href = github.min.css URL
DOM->>Browser: Request stylesheet
Browser->>CDN: Fetch github.min.css
CDN-->>Browser: CSS file
Browser->>Browser: Hash matches ✓
Browser->>DOM: Apply stylesheet
DOM->>User: Theme updated
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Problem
Three cross-origin assets in
static/index.htmlloaded without integrity attributes — the dashboard executed whatever the CDN delivered. Marked.js parses raw markdown and highlight.js runs on every code block, so a swapped payload would have full DOM access in our origin.Change
static/index.html—integrity="sha512-…"+crossorigin="anonymous"on all three CDN tags (highlight.js JS + CSS + marked.js).static/js/app.js— runtime theme swap previously rewrotehrefbetweenvs2015.min.cssandgithub.min.cssvia inline ternary. With integrity on the static tag, that would have left a stale hash at the moment of fetch and broken the UI on theme toggle. Replaced both inline sites with a const-map helper:Test plan
All four SHA-512 hashes verified two ways:
gh api 'https://api.cdnjs.com/libraries/<name>/<version>?fields=sri'curl -sL <url> | openssl dgst -sha512 -binary | base64Both methods agree for all four files (vs2015 / github CSS, highlight.min.js, marked.min.js).
End-to-end:
pytest tests/— 75/75 OK (no behaviour change in Python).integrity+crossoriginon all three CDN tags.http://127.0.0.1:5000/.Manual browser verification (DevTools → Console + Network):
github.min.cssfetched fresh with its own hash, page recolours, no SRI error.vs2015.min.cssre-fetches / cached, no SRI error.Forced negative test (optional): mutate one character of any
integrityattr → browser refuses the resource with the distinctiveFailed to find a valid digest in the 'integrity' attribute…console message. Confirms enforcement is real, not silently bypassed.Closes #19.
Summary by CodeRabbit
Release Notes
Bug Fixes
Security