Skip to content

Commit 3aa5d51

Browse files
Bump transitive linkify-it to 5.0.2 (GHSA-v245-v573-v5vm) (#11555)
Resolves the quadratic-complexity DoS advisory **GHSA-v245-v573-v5vm / CVE-2026-59887** in `linkify-it` ≤5.0.1, where the `mailto:` schema validator scans the full remaining tail per occurrence, yielding O(n²) work on attacker-controlled text. ### Changes - Bumped transitive dev dependency `linkify-it` **5.0.1 → 5.0.2** (patched version) in `packages/http-client-csharp/package-lock.json` via `npm update linkify-it --package-lock-only`. - Lock-file-only change; `package.json` untouched since `linkify-it` is transitive (pulled in via `markdown-it`). ### Reachability Assessment **Confidence: high — not actively reachable.** `linkify-it` is a **dev-only** transitive dependency via `markdown-it`, used at build/tooling time and not shipped in generated C# client output or fed untrusted text through the vulnerable `.test()`/`.match()` / `linkify:true` path. This update is primarily to satisfy vulnerability scanners rather than to address an active runtime risk. <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> ---- *This section details the Dependabot vulnerability alert you should resolve* <alert_title>linkify-it: Quadratic-complexity DoS via the `mailto:` validator scan-loop on attacker text</alert_title> <alert_description>### Summary `linkify-it`'s schema-scan loop (`.test()` / `.match()`, the documented public API) invokes the `mailto:` schema validator at **every** `mailto:` occurrence in the input text. For each occurrence the validator does `text.slice(pos)` (an O(n) copy) and runs an email regex whose local-part class `src_email_name` greedily scans the **entire remaining tail** (O(n)) before failing. With N `mailto:` occurrences that is **N × O(n) = O(n²)**. Because linkify-it runs on arbitrary user text (markdown-it feeds it whole documents when `linkify:true`), an unauthenticated attacker can block the single-threaded event loop for many seconds with a small input. No length bound (unlike an HTTP header). ### Root cause — `index.mjs` + `lib/re.mjs` ```js // index.mjs (mailto validator) — runs at every "mailto:" hit 'mailto:': { validate: function (text, pos, self) { const tail = text.slice(pos) // O(n) copy per hit if (!self.re.mailto) self.re.mailto = new RegExp('^' + self.re.src_email_name + '@' + self.re.src_host_strict, 'i') if (self.re.mailto.test(tail)) { ... } // scans the whole O(n) tail return 0 }} // lib/re.mjs:91-93 — every char of "mailto:" (incl. ':','-',';') is in this class: re.src_email_name = '[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]*' ``` The `while ((m = re.exec(text)) !== null) { …testSchemaAt… }` scan loop calls the validator at each `mailto:` hit; `src_email_name` greedily consumes the whole tail (all chars are in its class) then fails for lack of `@`. `http:`/`https:` do NOT blow up — their validator requires the tail to start with `//`, failing in O(1) per hit. ### Proof of Concept (confirmed, linkify-it 5.0.1, Node v24) ```js const LinkifyIt = require('linkify-it'); const lf = new LinkifyIt(); lf.match('mailto:'.repeat(48000)); // ~336 KB of "mailto:mailto:…" -> seconds of blocked event loop ``` | input (same bytes) | 56 KB | 112 KB | 224 KB | 336 KB | |---|---:|---:|---:|---:| | **`mailto:` contiguous** | 97 ms | 357 ms | 1438 ms | 3272 ms | | `mailto:` space-separated | 2 ms | 3 ms | 5 ms | 8 ms | | `http://` contiguous | 12 ms | 17 ms | 33 ms | 49 ms | ×~4 per 2× input ⇒ O(n²); equal-byte controls stay flat ⇒ algorithmic, not a GC/allocation artifact. Real-world via markdown-it 14.x (`{linkify:true}`), `md.render('mailto:'.repeat(n))`: 219 KB ≈ ~5 s. <img width="737" height="161" alt="image" src="https://github.com/user-attachments/assets/b5d390f3-68d0-4861-9c47-ad8aff0203d5" /> ### Impact Reachable on arbitrary user text via the documented `.test()`/`.match()` API and through markdown-it's linkifier — comment systems, chat, forums, wikis, note apps that render user markdown with linkify enabled. A ~220 KB post hangs the event loop ~5 s; a few hundred KB → tens of seconds. Availability only. ### Suggested remediation Bound the email local-part per RFC 5321 (≤64) so per-hit work is O(1), and avoid the full-tail slice: ```js // lib/re.mjs — cap the greedy run: re.src_email_name = '[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]{0,63}' // index.mjs — prefer a sticky regex anchored at `pos` over text.slice(pos). ``` ### Affected / disclosure All versions through 5.0.1 (latest); same code on `master`. cve-mcp/OSV report no known vulnerability for linkify-it. Distinct from markdown-it's own `*`-run ReDoS (CVE-2026-2327, different package/path) and the recent markdown-it DoS. Reported privately; happy to test a patch against the PoC.</alert_description> <severity>high</severity> <identifiers>GHSA-v245-v573-v5vm, CVE-2026-59887</identifiers> <package>linkify-it</package> <ecosystem>npm</ecosystem> <vulnerable_versions>5.0.1</vulnerable_versions> <patched_version>5.0.2</patched_version> <manifest_path>packages/http-client-csharp/package-lock.json</manifest_path> <references> <url>https://github.com/markdown-it/linkify-it/security/advisories/GHSA-v245-v573-v5vm</url> <url>https://nvd.nist.gov/vuln/detail/CVE-2026-59887</url> <url>https://github.com/markdown-it/linkify-it/commit/105e5d77f7d119871d2b2d86ed208568eb3e7ffe</url> <url>https://github.com/markdown-it/linkify-it/releases/tag/5.0.2</url> <url>https://github.com/advisories/GHSA-v245-v573-v5vm</url> </references> <task_instructions>Resolve this alert by updating the affected package to a non-vulnerable version. Prefer the lowest non-vulnerable version (see the patched_version field above) over the latest to minimize breaking changes. Include a Reachability Assessment section in the PR description. Review the alert_description field to understand which APIs, features, or configurations are affected, then search the codebase for usage of those specific items. If the vulnerable code path is reachable, explain how (whi... </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Resolves microsoft/typespec alert #761 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
1 parent f31cecc commit 3aa5d51

1 file changed

Lines changed: 3 additions & 3 deletions

File tree

packages/http-client-csharp/package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)