Repository navigation
fix: harden docs snippets, SVG sanitizer, lint regexes, GSAP writers and registry pins - #7512
Conversation
…vars argument The catalog preview embeds variable values as JSON that cannot close a script element or attribute, accepts value messages only from the page that embeds it, and reads only declared ids with primitive values from the link. The install command shell-quotes its --vars JSON and keeps only variable-id keys with primitive values. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…anitizer A browser folds CR LF, CR and form feed into one newline before it reads CSS escapes, so the whitespace after a hex escape can be a CR LF pair. The sanitizer now does the same, so an escaped function name split by a line ending is checked under its real name. The media-use bundle is regenerated from the source. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A getElementById template literal is matched against document ids with an in-order indexOf scan instead of a regex of joined wildcards, so the time no longer grows with the number of placeholders. The CSS rule scanners only start a match at the beginning of a brace-free run, which finds the same rules without rescanning long brace-less text. Lint results on every HTML file in the repository are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
String literals and quoted keys the GSAP writers emit now encode a script closer or comment opener as \u003c, so a value can no longer end the inline script that holds the timeline. Strings without those sequences are written exactly as before. The writers also refuse a tween method outside set, to, from and fromTo, and a motion path whose coordinates or curviness are not numbers, since both are emitted as code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The asset hosting script now refuses a manifest path that leaves the item directory or reaches its file through a symlink, before anything is read, staged, uploaded or removed. A repository test fails when the registry tracks a symlink or a manifest path that leaves its item. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The five map blocks load d3 7.9.2, the build the d3@7 range serves today, with a subresource integrity hash, and fetch us-atlas 3.0.1 and world-atlas 2.0.2, the files their ranges serve today. The bytes are unchanged, so the blocks render the same. A repository test fails when a registry item names an npm CDN package by range, tag or no version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7.9.0 has been the stable release since 2024; 7.9.1 and 7.9.2 were published days ago. Pin the long-standing version, with its subresource integrity hash. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
Restore the generated catalog pages and payloads, which the catalog publish job regenerates from the item sources. Name the us-atlas URL in us-map-flow so the call fits on one line and formatting is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Edit accuracy: accurate 267 (base branch 267), smooth 90 of thoseThe gate passes. Quarantined, measured but not gated (8)
Unstable (2)
|
There was a problem hiding this comment.
Verdict: REQUEST CHANGES · 1 blocker · 0 important · 2 nits · head ae81778
- blocker
packages/lint/src/rules/gsap.ts:426and:2354: both CSS-rule scans still use/(?<![^{}])([^{}]+)\{([^}]+)\}/g. The body[^}]+can cross{, so the scan is quadratic. A closed<style>holding"x{".repeat(40000)(80 KB) takes about 4.7 s per regex, andlintHyperframeHtmltakes about 10 s end to end (N=10k/20k: 271 → 1150 ms in plain node). This is a closed tag, not the "very large unclosed input" the body leaves out, and it contradicts "the CSS-rule scanners run in linear time". Fix: use a[^{}]+body or an indexOf scan, rerun the lint-parity check (nested@media … { .a {…}attribution), and add anx{×N timing test. - nit
sanitizeSvg.test.ts: the "CSS-escaped url() followed by a form feed" case passes on base, because the old[ \t\n\r\f]?already took a lone\f. Only the two CR LF cases are real regressions. - nit: the body has no
fails without the fix:line naming tests.
Scope
I ran 29 SVG bypass probes (xlink/aliased javascript:, external <use>, foreignObject, animate/set, mixed case, escaped url()/@import/image-set, feImage, PI, entities, CDATA), and all were stripped or inert. Also checked: the GSAP writers (no bare JSON.stringify left), registry asset hosting (realpath + O_NOFOLLOW), and the d3@7.9.0 sha384, which matches jsDelivr. Docs filters drop no real registry entry. Tests pass: parsers 8/8, core sanitizeSvg 59/59, lint gsap 241/241, and the node --test scripts. CI is green.
— Genesis
The two CSS-rule scans in the gsap rules took a body that could cross
'{', so a closed style of many '{' with no '}' rescanned to its end from
every brace. A scanner now returns the same selector and body pairs and
remembers the next '}', so each scan is linear. Findings are identical
on every tracked HTML file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review follow-up:
|
There was a problem hiding this comment.
Verdict: APPROVE — 2 resolved, 0 open, 0 new · ae81778 → 006da3d. styleRuleBodies is linear: 0 mismatches against the old regex on 300k random inputs of my own, and about 1 ms on x{/a{b{/}{/a{}×40k. The new timing test fails on the previous gsap.ts (9.0 s). lint gsap 242/242, sanitizeSvg 59/59. CI is green.
— Genesis
What
Hardening across the docs site, the SVG sanitizer, lint, the GSAP writers and the registry:
<style>holding many{with no}. The two gsap-rule scans use a small scanner that returns the same selector and body pairs as the old regex. Findings are identical on every tracked HTML file.</scriptand<!--in values they write into inline scripts, and refuse a tween method other thanset/to/from/fromToor a non-numeric motion-path value.scripts/host-registry-assets.tsrefuses paths outside the item and symlinks, with a test.d3@7.9.0,us-atlas@3.0.1andworld-atlas@2.0.2with subresource integrity, and a test rejects floating CDN versions.Why
Each change keeps untrusted text (composition HTML, URL parameters, SVG input, registry paths) from becoming code or reaching files it should not, and keeps third-party scripts from changing under a floating version.
Related work
#3953 also edits the map blocks and will need a small rebase after this lands.
How
Local fixes in each module. d3 is pinned to 7.9.0, the long-standing release (7.9.1 and 7.9.2 were published days ago); the producer's d3 fixture already uses 7.9.0.
Test plan
@mediablocks. The full lint (1288) and parsers (1426) suites pass.scripts/registry-cdn-pins.test.tspasses.scans a closed style block of many unclosed rules in linear time(lint, 2870 ms against a 2000 ms limit with the previous gsap.ts),matches a many-placeholder template id against a long near-miss id in linear time(lint),drops: CSS-escaped image-set() followed by CR LF in a style elementand... in style=(core), the six escaping, tween-method and motion-path cases ingsapWriter.scriptContext.test.ts(parsers),a manifest path outside the item is refused before anything is staged or removedandan asset that is a symlink is refused before its target is read(scripts), shown by running each test file with the merge-base version of the source it covers.scripts/catalog-detail.test.tsdoes not load without the fix, because the helpers it extracts are absent. The form-feed sanitizer case already passes on the base; it is kept as a guard for the line-ending fold.<script>/<style>lint regexes are still slow on very large unclosed input, server-side lint has no time budget yet, and the docs catalog preview is not moved to an opaque-origin sandbox (it would break the preview).🤖 Generated with Claude Code