Skip to content

fix(security): name font-src in the meta CSP so a font cannot load off-origin - #1284

Merged
mrbobbytables merged 1 commit into
mainfrom
sec/fix-csp-font-src
Oct 10, 2026
Merged

mrbobbytables merged 1 commit into
mainfrom
sec/fix-csp-font-src

Conversation

@hivecommons-hive

Copy link
Copy Markdown
Contributor

Security Fix

Claims exactly two files: the CSP directive list in docusaurus.config.js and
the CSP assertions in tests/site-config.test.mjs. Touches no gate module, no
validator and no importer, so it is disjoint from every other open PR.

The meta Content-Security-Policy ships no default-src, so every fetch
directive it does not name is unrestricted rather than inheriting a fallback —
the config's own comment says so. font-src was the last fetch directive still
unnamed, so the browser would fetch a font from any host. style-src carries
'unsafe-inline' (Docusaurus emits inline styles), so an inline @font-face
that reached a page could name one, disclosing every visitor's IP address,
User-Agent and Referer to that host.

This is the same asymmetry frame-src, media-src and connect-src were
added to close, on the same defence-in-depth footing: a backstop for the case
where a gate is bypassed, regresses, or a page is added without one. No current
bypass is known, so this is hardening, not an exploitable fix.

Why it could be set now

The directive was omitted only because nothing in the build asserted the
premise — the comment said so explicitly: "the site loads no remote font, but
nothing in the build asserts that, so the directive is left for a change that
can verify it."
This change supplies that assertion.

no shipped stylesheet names an off-origin font or other remote resource walks
every .css under src/ and fails if any url() resolves off-origin, judged
by remoteTarget() from scripts/lib/uri-safety.mjs — the same classifier the
SVG and MDX gates ask, so a protocol-relative or backslash-prefixed authority is
treated here exactly as it is there. The fonts themselves are vendored in
static/fonts/ and named by root-relative url('/fonts/ClarityCity-*.woff2'),
so 'self' constrains nothing the site actually does.

Verification

  • node --test tests/site-config.test.mjs: 28 pass, 0 fail.
  • Deleting the font-src line makes the new directive assertion fail
    (fail 1), so it pins the directive rather than passing vacuously.
  • NODE_ENV=production npx docusaurus build succeeds, and the emitted
    index.html carries ...; connect-src 'self'; font-src 'self'; form-action 'self'; ....
  • In that build, every url() in assets/css/*.css is same-origin or data:
    (zero matched neither), and every @font-face src is /assets/fonts/<file>,
    so nothing the site ships is blocked by the new directive.
  • prettier --check and eslint clean on both changed files.

Refs #1254 (the rest of that issue stays open: its primary subject is the MDX
remote-image gate in scripts/lib/mdx-active-content.mjs, which PR #1255
already covers; this PR deliberately changes no gate module. The CSP finding was
folded into #1254 by the hive's filename heuristic, not because the two share a
fix.)


Filed by sec-check agent (ACMM L4/L5 — hold-gated mode). Hold-gated: human review required.

— hive: agent=sec-check backend=copilot model=claude-opus-5 copilot=1.0.88

…f-origin

The meta Content-Security-Policy ships no default-src, so every fetch
directive it does not name is unrestricted rather than inheriting a
fallback. font-src was the last one still unnamed: the browser would
fetch a font from any host, and style-src carries 'unsafe-inline', so an
inline @font-face that reached a page could name one. A font fetch
discloses the visitor's IP, User-Agent and Referer to that host.

The directive was left out only because nothing in the build asserted
the premise that the site loads no remote font. It does now: the new CSS
scan fails if any url() in a shipped stylesheet resolves off-origin,
judged by remoteTarget() -- the same classifier the SVG and MDX gates
ask, so a protocol-relative or backslash-prefixed authority is treated
here exactly as it is there.

The site's fonts are vendored in static/fonts and named by root-relative
url(), so 'self' constrains nothing the site actually does.

Signed-off-by: sec-check <sec-check@hive.kubestellar.io>
@hivecommons-hive

Copy link
Copy Markdown
Contributor Author

Important

Held for human review by the hive's ACMM level gate.

This PR was opened by the "sec-check" agent while Hive policy required a human checkpoint for that agent. Non-outreach agents are held at ACMM L3–L5; the outreach agent is always held because it publishes project-facing communication.

Hive will keep the hold label until a human removes it. Operators can make a deliberate one-off release during an ACMM level change with release_level_holds=true, but level changes never release this hold automatically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant