Skip to content

Override transitive linkify-it to 5.0.2 to remediate mailto DoS - #2693

Draft
jainakanksha-msft with Copilot wants to merge 2 commits into
mainfrom
copilot/fix-vulnerability-linkify-it
Draft

Override transitive linkify-it to 5.0.2 to remediate mailto DoS#2693
jainakanksha-msft with Copilot wants to merge 2 commits into
mainfrom
copilot/fix-vulnerability-linkify-it

Conversation

Copilot AI commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

linkify-it is vulnerable to quadratic-time processing on attacker-controlled mailto: input (GHSA-v245-v573-v5vm / CVE-2026-59887). In this repo it is only introduced transitively through the VS Code packaging toolchain, but the resolved version in package-lock.json was still vulnerable.

  • What changed

    • Added an npm override in package.json to pin transitive linkify-it to the lowest patched version: 5.0.2
    • Regenerated package-lock.json so the resolved dependency graph no longer includes linkify-it@3.0.3
  • Why this path

    • linkify-it is not a direct dependency here
    • Dependency chain: vsce -> markdown-it -> linkify-it
    • Using an override keeps the change scoped to the vulnerable package without widening the update surface to unrelated tooling
  • Reachability Assessment

    • Confidence: High
    • Repository search found no direct imports or runtime call sites for markdown-it, linkify-it, or linkify: true usage under src/ or tests/
    • The vulnerable path is not reachable from Azurite service runtime; exposure is limited to dev/CI packaging flows that invoke vsce
  • Result

    • The repo now resolves linkify-it to a non-vulnerable version while preserving the existing vsce/markdown-it dependency chain
{
  "overrides": {
    "undici": "^7.28.0",
    "linkify-it": "5.0.2"
  }
}
Original prompt

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

// 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)

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.
image

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:

// 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>

high
GHSA-v245-v573-v5vm, CVE-2026-59887
linkify-it
npm
<vulnerable_versions>3.0.3</vulnerable_versions>
<patched_version>5.0.2</patched_version>
<manifest_path>package-lock.json</manifest_path>

https://github.com/markdown-it/linkify-it/security/advisories/GHSA-v245-v573-v5vm https://nvd.nist.gov/vuln/detail/CVE-2026-59887 https://github.com/markdown-it/linkify-it/commit/105e5d77f7d119871d2b2d86ed208568eb3e7ffe https://github.com/markdown-it/linkify-it/releases/tag/5.0.2 https://github.com/advisories/GHSA-v245-v573-v5vm

<agent_instructions>@copilot please go through the issues mentioned here, identify all issues, and assess whether they can be fixed.
Recommend the necessary changes.
If it is not a breaking change, let's log the issue.
Please verify all test cases and validate the runs.
</agent_instructions>

<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 Reachabili...

Copilot AI requested review from Copilot and removed request for Copilot August 3, 2026 08:20
Copilot AI changed the title [WIP] Fix DoS vulnerability in linkify-it mailto validator Override transitive linkify-it to 5.0.2 to remediate mailto DoS Aug 3, 2026
Copilot AI requested a review from jainakanksha-msft August 3, 2026 08:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants