Skip to content

fix(security): support SRI integrity verification for dashboard plugin scripts#19389

Closed
memosr wants to merge 1 commit into
NousResearch:mainfrom
memosr:fix/dashboard-plugin-csp-isolation
Closed

fix(security): support SRI integrity verification for dashboard plugin scripts#19389
memosr wants to merge 1 commit into
NousResearch:mainfrom
memosr:fix/dashboard-plugin-csp-isolation

Conversation

@memosr
Copy link
Copy Markdown
Contributor

@memosr memosr commented May 3, 2026

What does this PR do?

The dashboard plugin loader (web/src/plugins/usePlugins.ts) injects
plugin JS bundles as <script> tags in the main dashboard origin with
no integrity verification:

// Before (no integrity check)
const script = document.createElement("script");
script.src = scriptSrc;   // /dashboard-plugins/<name>/dist/index.js
script.async = true;
document.body.appendChild(script);

There is no:

  • integrity attribute (no Subresource Integrity)
  • Origin check before injection
  • Tamper detection between manifest registration and script load

A plugin script that runs in the main origin has full access to:

  • All cookies and localStorage on the dashboard origin
  • Every authenticated /api/... route — including session data,
    command approvals, credentials
  • The DOM of the main dashboard UI
  • window.__HERMES_* globals

If a plugin bundle is silently substituted (compromised plugin server,
MITM, malicious update), the loader will execute it with full origin
privileges and no warning.

Fix

Added opt-in support for the Subresource Integrity (SRI)
standard. Plugin manifests can now declare an integrity hash:

# manifest.yaml
name: my-plugin
entry: dist/index.js
integrity: "sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"

When the manifest declares an integrity field, the loader sets
script.integrity and script.crossOrigin = "anonymous":

if (manifest.integrity && typeof manifest.integrity === "string") {
  script.integrity = manifest.integrity;
  script.crossOrigin = "anonymous";
}

The browser then verifies the bundle's hash before executing — if the
file has been tampered with, the script is rejected and never runs.

Why opt-in?

Making integrity mandatory would break every existing plugin that
doesn't ship a hash. Opt-in lets plugin authors adopt it incrementally
while leaving room for stricter enforcement (e.g. a future config flag
that requires integrity for all plugins) once the ecosystem catches up.

A more comprehensive fix is iframe sandboxing, which would require
a plugin SDK redesign (postMessage API, no direct DOM access). That
refactor is out of scope for this PR — this fix is a low-risk
defense-in-depth improvement that ships immediately.

Type of Change

  • 🔒 Security fix (HIGH — defense in depth against compromised plugin delivery)

Checklist

  • Read the Contributing Guide
  • Commit messages follow Conventional Commits
  • PluginManifest interface updated with optional integrity field
  • No behavior change for plugins that don't declare integrity
  • Standards-based (Web SRI specification)

@alt-glitch alt-glitch added type/security Security vulnerability or hardening comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have labels May 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have type/security Security vulnerability or hardening

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants