Skip to content

fix: pin CDN scripts + theme CSS with SRI integrity hashes (closes #19)#20

Open
timon0305 wants to merge 2 commits intomasterfrom
fix/sri-cdn-scripts-19
Open

fix: pin CDN scripts + theme CSS with SRI integrity hashes (closes #19)#20
timon0305 wants to merge 2 commits intomasterfrom
fix/sri-cdn-scripts-19

Conversation

@timon0305
Copy link
Copy Markdown
Collaborator

@timon0305 timon0305 commented May 5, 2026

Problem

Three cross-origin assets in static/index.html loaded 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.htmlintegrity="sha512-…" + crossorigin="anonymous" on all three CDN tags (highlight.js JS + CSS + marked.js).

  • static/js/app.js — runtime theme swap previously rewrote href between vs2015.min.css and github.min.css via 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:

    const HLJS_THEME_SHEETS = {
      dark:  { href: '…vs2015.min.css',  integrity: 'sha512-…' },
      light: { href: '…github.min.css',  integrity: 'sha512-…' },
    };
    
    function applyHljsTheme(theme) {
      const link = document.getElementById('hljs-theme');
      if (!link) return;
      const sheet = HLJS_THEME_SHEETS[theme] || HLJS_THEME_SHEETS.dark;
      link.integrity = sheet.integrity;  // set FIRST so the browser sees it at fetch time
      link.href = sheet.href;
    }

Test plan

All four SHA-512 hashes verified two ways:

Method Source
gh api 'https://api.cdnjs.com/libraries/<name>/<version>?fields=sri' cdnjs's published SRI for the version
curl -sL <url> | openssl dgst -sha512 -binary | base64 Re-derived from the actual CDN response

Both 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).
  • ✅ Served HTML carries integrity + crossorigin on all three CDN tags.
  • ✅ App boots clean, returns HTTP 200 on http://127.0.0.1:5000/.

Manual browser verification (DevTools → Console + Network):

  1. First load — highlight.js, marked.js, vs2015.min.css all 200, no SRI error in Console.
  2. Toggle theme (sun/moon icon) — github.min.css fetched fresh with its own hash, page recolours, no SRI error.
  3. Toggle back — vs2015.min.css re-fetches / cached, no SRI error.

Forced negative test (optional): mutate one character of any integrity attr → browser refuses the resource with the distinctive Failed 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

    • Resolved an issue where code highlighting theme changes were not applied correctly.
  • Security

    • Added Subresource Integrity (SRI) verification for CDN-loaded assets to enhance security and prevent tampering.

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.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d1ff0fff-1b75-4f06-8fdb-2a28ed56cf6f

📥 Commits

Reviewing files that changed from the base of the PR and between ceefe1c and 4a33817.

📒 Files selected for processing (2)
  • static/index.html
  • static/js/app.js

📝 Walkthrough

Walkthrough

The pull request adds Subresource Integrity (SRI) support to CDN-loaded Highlight.js and Marked.js assets by appending integrity and crossorigin="anonymous" attributes to HTML tags, then centralizes runtime theme switching in a helper function that updates both href and integrity together to prevent SRI validation failures.

Changes

SRI Pinning and Theme-Aware Asset Loading

Layer / File(s) Summary
SRI Attributes
static/index.html
CDN <link> and <script> tags for Highlight.js and Marked.js now include integrity="sha384-..." and crossorigin="anonymous" attributes with explanatory comments about coordinated theme switching.
Theme Mapping & Helper
static/js/app.js (lines 3–29)
New HLJS_THEME_SHEETS object maps theme names to both href and integrity values; new applyHljsTheme(themeName) function updates the #hljs-theme link by setting integrity before href to maintain SRI validation during runtime swaps.
Theme Application Calls
static/js/app.js (lines 150–155, 858–862)
setWorkspaceMode(active) and applyTheme(theme) now invoke applyHljsTheme() instead of directly modifying hljsLink.href alone.

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 Hop-hop, the hashes align!
Integrity pinned, the CDN's fine,
Theme swaps now dance both href and hash,
No ghostly attacks, no style clash! 🎨✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: pin CDN scripts + theme CSS with SRI integrity hashes (closes #19)' accurately and concisely describes the main security fix adding SRI integrity attributes to CDN assets and addressing runtime theme swapping.
Linked Issues check ✅ Passed The pull request successfully implements all coding objectives from issue #19: adds integrity and crossorigin attributes to three CDN tags, replaces inline ternary with HLJS_THEME_SHEETS const map, and updates both call sites in app.js to use applyHljsTheme() for coordinated href/integrity updates.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #19: HTML integrity attributes, JavaScript theme-swap refactoring, and related helper function. No unrelated modifications detected beyond the stated objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sri-cdn-scripts-19

Comment @coderabbitai help to get the list of available commands and usage tips.

@timon0305 timon0305 self-assigned this May 5, 2026
@timon0305 timon0305 requested a review from clean6378-max-it May 5, 2026 16:43
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: add SRI integrity attributes to CDN-loaded highlight.js, marked.js, and theme CSS

1 participant