Skip to content

LTS-4657: override ip-address to ^10.4.0 — fixes GHSA-mwp4-54f8-5fhr (leading-zero octet SSRF) - #20

Merged
SaranshBS merged 1 commit into
mainfrom
LTS-4657-ip-address-ssrf-bump
Aug 7, 2026
Merged

LTS-4657: override ip-address to ^10.4.0 — fixes GHSA-mwp4-54f8-5fhr (leading-zero octet SSRF)#20
SaranshBS merged 1 commit into
mainfrom
LTS-4657-ip-address-ssrf-bump

Conversation

@MihirR-BS

@MihirR-BS MihirR-BS commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Fixes LTS-4657GHSA-mwp4-54f8-5fhr (High).

What changed

One line in overrides + the matching lock entry. ip-address 10.2.0 → 10.4.0.

   "serialize-javascript": "^7.0.3",
+  "ip-address": "^10.4.0",

Why

Address4 accepted an octet with a leading zero and decoded it as decimal, while the WHATWG URL parser, inet_aton and getaddrinfo decode it as octal. So new Address4('012.0.0.1').isPrivate() returned false while fetch('http://012.0.0.1/') connects to 10.0.0.1. Every classifier built on parse inherits it — isPrivate(), isLoopback(), isLinkLocal(), isCGNAT(), isInSubnet(), isHostInSubnet(), correctForm().

Where it comes from

ip-address is not a direct dependency. Single copy in the tree, dev: true, pulled by socks (^10.1.1):

ip-address <- socks <- socks-proxy-agent <- @kubernetes/client-node <- browserstack-node-sdk
                    <- socks-proxy-agent <- pac-proxy-agent <- proxy-agent <- @puppeteer/browsers <- @wdio/utils <- @wdio/cli

Blast radius

Scope devDependencies only — this repo declares no runtime dependencies
Reachability here Latent. socks uses ip-address to parse SOCKS proxy target addresses. Nothing in this sample makes a trust-boundary decision from Address4, and no SSRF filter is built on it.
Attack vector Needs an application that gates untrusted host input on isPrivate()/isInSubnet(). Not a shape this repo has.
Blast radius of the fix 10.4.0 has no dependencies and the same engines (node >= 12) as 10.2.0. socks asks for ^10.1.1, which 10.4.0 satisfies — no resolution changes anywhere else in the tree.

Bumped anyway because this is a public, customer-facing sample: customers clone it and run npm install, so a High advisory sitting in the lock is a bad look regardless of local reachability — and it is a 4-line diff.

Coverage

10.4.0 clears all three open ip-address advisories against the installed 10.2.0, not just the one on the ticket:

Advisory Severity Vulnerable Patched
GHSA-mwp4-54f8-5fhr High <= 10.3.0 10.3.1
GHSA-4xrf-jv44-h6hh Medium 10.1.1 – 10.2.1 10.2.2
GHSA-22jq-vg5j-6vgg Medium 10.1.1 – 10.2.0 10.2.1

Corresponding Dependabot alerts: #132, #126, #125.

^10.4.0 rather than the 10.3.1 floor — 10.4.0 is latest, published 2026-07-31, so it clears the repo's .npmrc min-release-age=7 guard, and it matches the ^10.4.0 pin already chosen for load-testing-backend.

Verification

$ npm ci                          # clean install from this lock — succeeds, PMG guard passes
$ npm ls ip-address --all
  └── ip-address@10.4.0 overridden
$ npm audit                       # ip-address no longer reported
$ npx wdio --version
  9.29.1

Advisory PoC against the installed tree — now behaves as the patched release documents:

$ node -e "const {Address4}=require('ip-address'); ..."
isValid(012.0.0.1) = false        (was: true, correctForm 12.0.0.1, isPrivate false)
constructor throws: AddressError
isValid(10.0.0.1)  = true         (legitimate addresses unaffected)

Note on the lockfile diff

The lock hunk is hand-scoped to the three ip-address fields (version / resolved / integrity). A full npm install --package-lock-only on npm 10.9.2 additionally strips 11 unrelated "peer": true markers; that churn is inert but noise in a security PR, so it was reverted. integrity was verified against npm view ip-address@10.4.0 dist.integrity, and npm ci was run from the resulting lock.

Not fixed here

npm audit still reports 11 findings (5 high / 6 moderate) on this branch — brace-expansion, fast-uri, fast-xml-parser, js-yaml, undici, qs, uuid, gaxios, googleapis*. The first three are already covered by open PR #19 (LTS-4523). The rest are out of scope for this ticket.

🤖 Generated with Claude Code

…(leading-zero octet SSRF)

ip-address 10.2.0 arrives transitively via socks (^10.1.1) under
browserstack-node-sdk -> @kubernetes/client-node -> socks-proxy-agent, and via
proxy-agent/pac-proxy-agent under @wdio/utils. Address4 decoded a leading-zero
octet as decimal while resolvers decode it as octal, so isPrivate()/isInSubnet()
could misclassify an internal target as public.

10.4.0 clears all three open advisories on the installed 10.2.0:
  GHSA-mwp4-54f8-5fhr (high,   <= 10.3.0)          patched 10.3.1
  GHSA-4xrf-jv44-h6hh (medium, 10.1.1 - 10.2.1)    patched 10.2.2
  GHSA-22jq-vg5j-6vgg (medium, 10.1.1 - 10.2.0)    patched 10.2.1

Verified: npm ci from this lock installs ip-address@10.4.0 (overridden),
npm audit no longer reports ip-address, and the advisory PoC now behaves as
patched — Address4.isValid('012.0.0.1') === false and the constructor throws
AddressError, while '10.0.0.1' still parses.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@MihirR-BS
MihirR-BS requested a review from a team as a code owner August 7, 2026 12:20
@MihirR-BS
MihirR-BS requested a review from nikhils08 August 7, 2026 12:20
@SaranshBS
SaranshBS merged commit 6118965 into main Aug 7, 2026
5 checks passed
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.

3 participants