chore: version packages - #806
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
eslint-plugin-react-doctor@0.5.4
Patch Changes
eacdcf2,eacdcf2]:oxlint-plugin-react-doctor@0.5.4
Patch Changes
#744
eacdcf2Thanks @aidenybai! - Add a project-level security file scan: 36 first-class scan rules (leaked artifact secrets and env dumps, permissive Firebase/Supabase rules, raw SQL injection risk, unsafe webhook signature comparisons, committed private key material, public debug artifacts, …) ship in the oxlint plugin as ordinarydefineRulemodules that declare a project-levelscaninstead of AST visitors and run in@react-doctor/core's environment-check phase over one bounded whole-tree walk — covering shipped bundles, dotenv/config files, SQL, and Firebase rules files that per-file linting never sees.Scan rules register metadata (id, title, severity, recommendation,
Securitycategory,security-scantag) like any other rule but carry a project-levelscaninstead of AST visitors, so their findings flow through the standard diagnostic pipeline: per-rule and per-category severity overrides, inline disables, and outputsurfacesnow apply to scan-rule diagnostics, andreact-doctor rules ignore-tag security-scan(configignore.tags) silences the whole family. They never appear in generated oxlint configs or the ESLint presets — they only execute through React Doctor's scan. A plain--diff/--stagedscan skips them like the other whole-project checks, and the gate is now diff mode itself rather than the presence of include paths, so projects configuringignore.filesget the security scan too.#744
eacdcf2Thanks @aidenybai! - Fixed false positives indangerous-html-sink(the highest-volume new rule) reported by RDE evals onrepos.json(200 rootDir scans / 19 distinct repos / 51 total new security diagnostics).packages/emails, dubpackages/email, etc.) were reported even though the rule intends to exempt them (mail clients strip scripts; browser XSS model does not apply). TheEMAIL_TEMPLATE_PATH_PATTERNskip only looked at the scan-relative path and missed cases whererootDirwas already the emails package (relativePath =src/components/RawHtml.tsx).renderHtmlFromRichText(editor, richText)result assigned to barehtmlthen used at a sink in labels) were not recognized, unlike the existing katex / renderToStaticMarkup / hast-util cases inESCAPING_SERIALIZER_LIBRARY_PATTERN. Same shape as the "KaTeX-rendered html identifiers" regression that already passes.Updated
EMAIL_TEMPLATE_PATH_PATTERN(now also matches RawHtml and *Email filenames) andESCAPING_SERIALIZER_LIBRARY_PATTERN(addedrenderHtmlFromRichText). Added two regression tests using the exact hit shapes from the 51-eval corpus.A second eval pass (replaying the rule against every corpus hit's real source) surfaced four more false-positive classes, now fixed:
el.innerHTML = '' // clearwas flagged because the trailing line comment defeatedSTRING_LITERAL_VALUE_PATTERN, after which the value scan bled into the next statement and tainted on an unrelated token there (PostHogNotebookNodeLatexreadingcontenton the following line). The literal/constant exemptions now tolerate a trailing line comment.createHTMLDocument()parse-to-text — a disconnected document (no browsing context, scripts never run) used to strip tags to text (tldrawstripHtml) is now treated as inert.createElementscratch nodes — a node that is parsed, then queried / read back, and never attached to a live tree nor returned as a node (Planepaste-asset) is now inert; the existing "parsed HTML reaches the document" guard still fires when the node is appended.render*HTML(...)serializers (pierrerenderPartialHTML) and highlighter output stored on an object (highlightedFiles[0].darkHtml, shiki) are exempt when a serializer library is present in the file, matching the existing bare-identifier handling.Added seven regression tests (including a still-fires guard for object-stored HTML with no serializer library and for scratch nodes appended to the live tree) using the exact hit shapes from the corpus.
A full-corpus replay (8k+ rootDir scans) surfaced three more false-positive classes, now fixed:
dangerous-html-sinknow skips files the walker flagged as generated bundles (e.g. a minifiediconfont.jswhose inline SVG string tripped the line heuristics). XSS-sink review is for human-authored source, not build output.const clean = DOMPurify.sanitize(md.render(x))then__html: cleanis now exempt: a bare-identifier value is traced to aDOMPurify/sanitize(...)/purify(...)assignment in the file (the sink only sees the identifier).encode*entity encoders (encodeNonAsciiHTML) join the existingescape*recognition as escaped, non-live output.Added four more regression tests (including a still-fires guard for a bare identifier that is never sanitized in the file).
A wider corpus pass added three further false-positive classes:
target.innerHTML = other.innerHTML/= other.outerHTML(optionally with a.replace/.trimtransform) re-serializes content already in the document, so it is no injection boundary (a+concatenation is still judged, to catch spliced-in input).__html: htmlSanitizedis now recognized (thesanitizeconvention previously required a word boundary the camelCase name lacked).hljsResult.value) is exempt.Added five more regression tests (including a still-fires guard for DOM content concatenated with fresh input).
Two final classes from the corpus tail:
//line comment or a block-comment line is no longer flagged (commented-out code never runs); a://in a URL on the same line does not trip the guard.<style>element innerHTML —createElement('style')thenel.innerHTML = cssinjects CSS text, not executable markup (the DOM-API counterpart of the existing<style dangerouslySetInnerHTML>exemption).Added three more regression tests.
A
/thermosreview pass hardened the exemptions against false negatives (a security rule must not hide a real sink), tightening the looser ones this changeset added:const html = katex.renderToString(...)) — sharing one assignment-check path with the sanitizer exemption.isInertParseTargetforces non-inert when the target name is ever bound to a live DOM node (getElementById/querySelector/.current/document.body), closing same-name collisions across functions.a.innerHTML.replace(x, props.userHtml)), not only on+concatenation.escape/encodesanitizer arm is scoped to HTML encoders (soencodeURIComponent/escapeRegExp/encodeForDisplayno longer exempt)."//cdn") before a real sink is not mistaken for a//comment.Added FN-guard regression tests for each (49 tests total).
A second full-corpus pass found the largest remaining false-positive class — syntax-highlighter output — and two smaller ones:
highlightedHtml,file.highlightedContent,highlight*()calls) is escaped, token-wrapped markup. It is usually routed through React state (const [highlightedHtml, setHighlightedHtml] = useState(); setHighlightedHtml(await codeToHtml(code))) or passed as a prop, so the data-flow assignment check never sees it. Now exempt:highlight*()calls (escaping serializers),highlighted*values (escaped-output naming convention), and present-tensehighlight*values when the file uses a highlighter library (Shiki/Prism/highlight.js/…).Svg?.outerHTML).<textarea>HTML-entity decode idiom (textArea.innerHTML = x; return textArea.value) — textarea content is RCDATA, so scripts never execute — joins the<style>inert-element exemption.Added six FN-guard regression tests (incl. a non-highlighter
renderedHtmland a present-tensehighlight*with no library still firing). 56 tests total.Detection coverage (recall)
Beyond precision,
dangerous-html-sinkwas missing real DOM-XSS — a security rule must catch the dangerous cases, not just stay quiet. Added:dangerouslySetInnerHTMLandinnerHTML =, the rule now flagsouterHTML =assignments,el.insertAdjacentHTML(position, html)(the value is the second argument),document.write(ln)(html),Range.createContextualFragment(html), and the explicitly-unsafeElement.setHTMLUnsafe(html)(the sanitizingsetHTMLis intentionally not a sink).location.hash/.search/.href,document.cookie,document.referrer,window.name,localStorage/sessionStorage, andURLSearchParams(matched at word boundaries / on the source expression so identifier names likethemeLocalStorageKeydo not false-match).Verified against the cached corpus: the new sinks surface previously-missed real injections (e.g.
el.insertAdjacentHTML(pos, content),node.outerHTML = html,document.write(editor.getContent())) while the exemption pipeline and theisGeneratedBundleskip keep minified-vendor noise out. Added 7 detection tests (5 must-fire DOM-XSS cases + 2 still-silent guards for staticinsertAdjacentHTMLandouterHTML-to-outerHTMLserialization).A RDE parity pass against
mainsurfaced three more false positives, now fixed:mcp-tool-capability-riskkeyed its surface on every MCP entry point, so it flaggednew McpServer({...})construction and staticregisterPrompt(...)calls whenever the file mentioned any capability. It now only matches actual TOOL handlers (server.tool(,registerTool(,setRequestHandler(CallToolRequestSchema)) — model-controlled action surfaces — not construction, tool listing, prompts (message templates), or resources (read-only). Added a regressions test (FP guards for construction/prompt + true-positive tool handlers).dangerous-html-sinknow exempts capture-and-restore of a node's own serialized content (const original = el.innerHTML; … el.innerHTML = original) — restored markup never left the document — while still flagging a captured value concatenated with fresh input. It also recognizes Mermaid diagram output (const svg = (await mermaid.render(...)).svg) as escaping-serializer output, alongside KaTeX/Shiki/Prism.This hardens the 6 new security-scan rules (
dangerous-html-sink,clickjacking-redirect-risk,insecure-crypto-risk,mcp-tool-capability-risk,raw-sql-injection-risk,url-prefilled-privileged-action) that landed in the posture scanner.react-doctor@0.5.4
Patch Changes
#744
eacdcf2Thanks @aidenybai! - Add a project-level security file scan: 36 first-class scan rules (leaked artifact secrets and env dumps, permissive Firebase/Supabase rules, raw SQL injection risk, unsafe webhook signature comparisons, committed private key material, public debug artifacts, …) ship in the oxlint plugin as ordinarydefineRulemodules that declare a project-levelscaninstead of AST visitors and run in@react-doctor/core's environment-check phase over one bounded whole-tree walk — covering shipped bundles, dotenv/config files, SQL, and Firebase rules files that per-file linting never sees.Scan rules register metadata (id, title, severity, recommendation,
Securitycategory,security-scantag) like any other rule but carry a project-levelscaninstead of AST visitors, so their findings flow through the standard diagnostic pipeline: per-rule and per-category severity overrides, inline disables, and outputsurfacesnow apply to scan-rule diagnostics, andreact-doctor rules ignore-tag security-scan(configignore.tags) silences the whole family. They never appear in generated oxlint configs or the ESLint presets — they only execute through React Doctor's scan. A plain--diff/--stagedscan skips them like the other whole-project checks, and the gate is now diff mode itself rather than the presence of include paths, so projects configuringignore.filesget the security scan too.#744
eacdcf2Thanks @aidenybai! - Remove the--sfwdemo flag (the standalone Socket.dev supply-chain score listing that printed every direct dependency's score and exited).The Socket.dev supply-chain check is unaffected — it still runs during normal full scans (and on diff scans whose
package.jsonchanged) and its scores still appear in the JSON report. Only the standalone listing is gone, along with its demo-only internals (collectSupplyChainScores, theDependencyScoretype, the monorepo-wide dependency collector, and the score-table renderer).Updated dependencies [
eacdcf2,eacdcf2]:@react-doctor/api@0.5.4
Patch Changes
eacdcf2]:@react-doctor/core@0.5.4
Patch Changes
#744
eacdcf2Thanks @aidenybai! - Add a project-level security file scan: 36 first-class scan rules (leaked artifact secrets and env dumps, permissive Firebase/Supabase rules, raw SQL injection risk, unsafe webhook signature comparisons, committed private key material, public debug artifacts, …) ship in the oxlint plugin as ordinarydefineRulemodules that declare a project-levelscaninstead of AST visitors and run in@react-doctor/core's environment-check phase over one bounded whole-tree walk — covering shipped bundles, dotenv/config files, SQL, and Firebase rules files that per-file linting never sees.Scan rules register metadata (id, title, severity, recommendation,
Securitycategory,security-scantag) like any other rule but carry a project-levelscaninstead of AST visitors, so their findings flow through the standard diagnostic pipeline: per-rule and per-category severity overrides, inline disables, and outputsurfacesnow apply to scan-rule diagnostics, andreact-doctor rules ignore-tag security-scan(configignore.tags) silences the whole family. They never appear in generated oxlint configs or the ESLint presets — they only execute through React Doctor's scan. A plain--diff/--stagedscan skips them like the other whole-project checks, and the gate is now diff mode itself rather than the presence of include paths, so projects configuringignore.filesget the security scan too.Updated dependencies [
eacdcf2,eacdcf2]:@react-doctor/language-server@0.5.4
Patch Changes
eacdcf2]:Note
Medium Risk
The diff is mechanical, but merging publishes security-scan behavior and new diagnostics on full scans, which can change CI scores and failure gates for consumers.
Overview
Release-only PR — no application code in the diff. It drops three consumed changesets and bumps the monorepo from 0.5.3 → 0.5.4 (
react-doctor,@react-doctor/core,oxlint-plugin-react-doctor,eslint-plugin-react-doctor,@react-doctor/api,@react-doctor/language-server) with matching CHANGELOG entries.What 0.5.4 documents as shipping (from #744):
Adds a project-level security file scan: 36
defineRulemodules with ascanhook (not AST visitors) run in core’s environment-check phase over a whole-tree walk (bundles, env/config, SQL, Firebase rules, etc.). Findings use the normal diagnostic pipeline (security-scantag,ignore.tags, surfaces); scan rules are not emitted to generated oxlint/ESLint configs. Full scans run the scan;--diff/--stagedskip it, with the gate tied to diff mode soignore.filesno longer suppresses the security scan.CLI: removes the
--sfwdemo (standalone Socket.dev score table); the in-scan supply-chain check and JSON scores are unchanged.Rules: large
dangerous-html-sinkprecision/recall work (exemptions, more sinks/taint sources) andmcp-tool-capability-risklimited to real tool handlers, plus hardening for the six posture security rules.Reviewed by Cursor Bugbot for commit 72f58fa. Bugbot is set up for automated code reviews on this repo. Configure here.