All vulnerabilities
GHSA-2rg9-wxfw-wrr7

@pdfme/common: isUrlSafeToFetch bypass via IPv4-mapped IPv6, [::] and localhost. (incomplete fix of GHSA-pgx6-7jcq-2qff)

@pdfme/common
CVSS
3.7Low
ExploitationNo known exploitationNot in CISA KEV, which does not prove it is unexploitedCISA KEV
Exploit odds (EPSS)No scoreNo FIRST EPSS score in this snapshot yet
Fixed in6.2.6Fixed versionGitHub
Published16 Oct 2026Updated 16 Oct 2026GitHub

What fixes it

  • 6.2.6@pdfme/common, npmGitHubnpm install @pdfme/common@6.2.6

A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.

Description

Summary

The fix for GHSA-pgx6-7jcq-2qff added isUrlSafeToFetch, which getB64BasePdf calls before fetch(basePdf). It is a string denylist on new URL(x).hostname. WHATWG URL normalises IPv4-mapped IPv6 to hex (new URL('http://[::ffff:127.0.0.1]/').hostname === '[::ffff:7f00:1]'), so the dotted-quad mapped-address check never matches. [::], NAT64 and trailing-dot localhost. are not covered either.

Affected

@pdfme/common 6.2.5 (latest), isUrlSafeToFetch / getB64BasePdf in dist/index.js (around lines 436-467 and 597-600).

Reproduction

node 22, Docker with --network none, calling the exported isUrlSafeToFetch:

http://127.0.0.1/              false
http://169.254.169.254/        false
http://[::ffff:127.0.0.1]/     true
http://[::ffff:7f00:1]/        true
http://[::ffff:a9fe:a9fe]/     true   (169.254.169.254, cloud metadata)
http://[::]/                   true
http://localhost./             true

The plain loopback and metadata addresses are rejected (control). Their IPv4-mapped forms, [::] and localhost. are reported safe and would be fetched.

Impact

Same scenario as GHSA-pgx6-7jcq-2qff: an attacker who controls a template's basePdf makes the runtime fetch internal URLs, including cloud metadata, and the response is embedded as the base PDF. The fetch runs where window is defined (browser or a server-side DOM shim). Estimated CVSS 3.1 AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N.

Suggested fix

Parse the hostname with an IP library, unwrap IPv4-mapped and NAT64 addresses to IPv4, reject every non-global address (including :: and 0.0.0.0/8), and strip a trailing dot before comparing hostnames.

Found with AploSec.

Reported by Zachariah Mithani (zachariah@aplosai.com).

Text from GitHub Advisory Database

Affected versions 1

  • @pdfme/common, npm>= 5.5.10, < 6.2.6GitHub