Plugin Content Security

Security model for plugin content.

Plugin Content Security

Fortemi does not execute remote plugin UI by default. Hosts that opt into plugin-loaded scripts must enforce three controls before a script is loaded:

1. A restrictive Content Security Policy. 2. Operator allowlisting for every plugin script origin or exact URL. 3. Subresource Integrity for every external script.

Default CSP

Use buildPluginCsp() from @fortemi/core when emitting headers or HTML meta tags for a host application.

Example:

import { buildPluginCsp } from "@fortemi/core" const policy = buildPluginCsp({ scriptSrc: ["https://plugins.example.org"], connectSrc: ["https://plugins.example.org"], reportUri: "/api/csp-report", }) response.headers.set("Content-Security-Policy-Report-Only", policy)

The generated baseline includes default-src self, object-src none, and script-src self strict-dynamic. Run new deployments in report-only mode first. After the report stream is clean, move the same policy to Content-Security-Policy.

Script Allowlist

Operators must approve each plugin origin or exact script URL. A wildcard origin is accepted by the API for controlled private deployments, but public or multi-tenant hosts should not use it.

import { fetchPluginScript } from "@fortemi/core" const plugin = await fetchPluginScript( { url: "https://plugins.example.org/plugin-a/index.js", integrity: "sha384-base64digest", }, { allowedOrigins: ["https://plugins.example.org"], allowedUrls: ["https://plugins.example.org/plugin-a/index.js"], }, )

fetchPluginScript() fails before network access when the URL is not allowlisted or when an integrity value is missing. It fetches the script bytes, verifies SRI, and returns the script text for a host-controlled loader.

Browser hosts that intentionally append a module script can use appendPluginScript(). It applies the same allowlist and SRI requirements before adding the script tag.

Subresource Integrity

Integrity values use standard SRI syntax, for example sha384-BASE64_DIGEST.

Use computeSri(bytes) when publishing a plugin artifact and verifySri(bytes, integrity) before loading. Fortemi supports sha256, sha384, and sha512; sha384 is the default.

An SRI mismatch is a load failure. Hosts must surface that failure as a plugin installation or activation error, not retry from a different URL.

CSP Reports

Mount createCspReportHandler() at the report URI used in the CSP. The handler accepts browser report-uri payloads and normalized Reporting API payloads, then calls your telemetry sink.

import { createCspReportHandler } from "@fortemi/core" const handleCspReport = createCspReportHandler(async report => { await telemetry.write({ type: "csp_violation", blockedUri: report.blockedUri, effectiveDirective: report.effectiveDirective, originalPolicy: report.originalPolicy, }) })

Do not include secrets in plugin URLs or CSP report paths. Browsers may include blocked URLs in violation payloads.

Operator Checklist

  • Start with Content-Security-Policy-Report-Only and a configured report URI.
  • Add plugin origins only after operator approval.
  • Require SRI for every external plugin script.
  • Treat SRI mismatch, missing SRI, and non-allowlisted origin as hard failures.
  • Review CSP reports before enforcing the policy.
  • Document every approved plugin origin in deployment configuration.