Back to Blog
high SEVERITY7 min read

How IP Address Parsing Inconsistency Happens in Node.js and How to Fix It

CVE-2026-69192 revealed a critical inconsistency in the `ip-address` npm package where the `Address4` class decoded leading-zero octets as decimal while standard DNS resolvers interpreted them as octal, creating a trust-boundary bypass and SSRF attack vector. The fix upgrades `ip-address` from version 10.2.0 to 10.3.1 in the CanvaLight plugin, correcting the parsing behavior to match resolver expectations.

O
By Orbis AppSec
•Published August 9, 2026•Reviewed August 9, 2026

Answer Summary

CVE-2026-69192 is an IP address parsing inconsistency vulnerability (CWE-1025: Comparison Using Wrong Factors) in the Node.js `ip-address` package where the `Address4` decoder treats leading-zero octets as decimal while DNS resolvers interpret them as octal. This mismatch allows attackers to bypass IP-based trust boundaries and execute SSRF attacks. The fix upgrades `ip-address` to version 10.3.1, which corrects the octal interpretation to align with standard resolver behavior.

Vulnerability at a Glance

cweCWE-1025 (Comparison Using Wrong Factors), CWE-436 (Interpretation Conflict)
fixUpgrade `ip-address` from 10.2.0 to 10.3.1 to correct octal interpretation
riskServer-Side Request Forgery (SSRF), trust-boundary bypass, IP-based access control bypass
languageJavaScript/Node.js
root causeThe `ip-address` package's `Address4` class decoded leading-zero octets as decimal instead of octal, diverging from standard resolver behavior
vulnerabilityIP Address Parsing Inconsistency (Leading-Zero Octet Mismatch)

How IP Address Parsing Inconsistency Happens in Node.js and How to Fix It

The Vulnerability Explained

In the CanvaLight plugin's dependency tree, a subtle but critical flaw existed in the ip-address npm package (version 10.2.0). The Address4 class—responsible for parsing IPv4 address strings—had a parsing inconsistency that could silently bypass IP-based trust boundaries.

The Core Problem:

The ip-address library decoded leading-zero octets as decimal numbers, while standard DNS resolvers and most operating systems decode them as octal. This created a dangerous divergence:

  • What the ip-address library saw: 010.0.0.1 → parsed as 10.0.0.1 (decimal interpretation of 010)
  • What DNS resolvers saw: 010.0.0.1 → parsed as 8.0.0.1 (octal interpretation of 010)

For applications using the ip-address library to validate or filter requests against IP whitelists, an attacker could craft a malicious request with a leading-zero IP address that would:
1. Pass validation checks in the application (because ip-address decoded it as expected)
2. Resolve to a different IP address at the DNS/resolver level (because resolvers use octal)
3. Reach an internal or restricted service that the application thought it was blocking

Why This Matters for CanvaLight

The CanvaLight plugin (in plugins/canvasight/package-lock.json) depends on ip-address for network operations. If CanvaLight uses this library to:
- Validate client IP addresses against a whitelist
- Construct URLs for internal service calls
- Parse proxy headers
- Implement IP-based rate limiting

...then an attacker could exploit the parsing mismatch to:
- Bypass IP-based access controls
- Perform Server-Side Request Forgery (SSRF) attacks against internal services
- Access restricted resources that should have been blocked

Real-World Attack Scenario

Imagine CanvaLight has a whitelist: ["192.168.1.100", "192.168.1.101"]. An attacker crafts a request with the IP 192.0168.1.100 (leading zero in the second octet):

GET /api/internal HTTP/1.1
X-Forwarded-For: 192.0168.1.100
  1. CanvaLight's validation (using ip-address 10.2.0):
    - Parses 192.0168.1.100 → 192.8.1.100 (octal: 0168 = 8 in decimal... wait, no)
    - Actually: 192.0168.1.100 → 192.168.1.100 (decimal interpretation of 0168 = 168)
    - ✅ Matches whitelist → Request allowed

  2. DNS resolver (standard behavior):
    - Parses 192.0168.1.100 → 192.8.1.100 (octal: 0168 = 8)
    - ❌ Does not match whitelist → But resolver already resolved to 192.8.1.100
    - Request reaches 192.8.1.100 instead of the expected service

This is a trust-boundary bypass: the application and the resolver disagree on what IP address was requested.


The Fix

The fix upgrades the ip-address package from 10.2.0 to 10.3.1 in both package.json and package-lock.json:

Before (Vulnerable)

"node_modules/ip-address": {
  "version": "10.2.0",
  "resolved": "https://registry.npmmirror.com/ip-address/-/ip-address-10.2.0.tgz",
  "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
  "license": "MIT",
  "peer": true,
  "engines": {

After (Fixed)

"node_modules/ip-address": {
  "version": "10.3.1",
  "resolved": "https://registry.npmmirror.com/ip-address/-/ip-address-10.3.1.tgz",
  "integrity": "sha512-1e9d3kb97NHJTIJDZW9rKqW2h6+dFa50Dy0fpPSMQp2ADje5gvKsXmdiK6dwY5t76TaTt5+P5N1Y/LoToIxP6g==",
  "license": "MIT",
  "peer": true,
  "engines": {

What Changed in Version 10.3.1

The ip-address 10.3.1 release corrected the Address4 parser to:

  1. Properly interpret leading-zero octets as octal, aligning with RFC standards and resolver behavior
  2. Validate that octal octets don't exceed 255 (since 0377 in octal = 255 in decimal, the maximum valid octet value)
  3. Reject invalid octal sequences that would produce out-of-range values

Now, when the parser encounters 010.0.0.1:
- It correctly interprets 010 as octal → 8 in decimal
- Result: 8.0.0.1 (matches DNS resolver behavior)
- Applications using this library now have consistent parsing across the entire stack

Why This Specific Fix Works

By upgrading to 10.3.1, the CanvaLight plugin now:
- ✅ Parses IP addresses consistently with DNS resolvers and OS-level network stacks
- ✅ Prevents attackers from crafting octal-encoded IPs to bypass validation
- ✅ Maintains backward compatibility for valid IP addresses (no leading zeros or standard decimal notation)
- ✅ Closes the trust-boundary gap that enabled SSRF attacks


Key Takeaways

  • Leading-zero octets are octal, not decimal: The ip-address 10.2.0 library incorrectly parsed 010 as 10 instead of 8, breaking trust boundaries. Always verify your parser matches standard resolver behavior.

  • Trust-boundary misalignment is a security risk: When your application and your network stack disagree on what an IP address means, attackers can exploit the gap. This specific vulnerability allowed SSRF by making whitelisted IPs resolve to different addresses.

  • Upgrade ip-address to 10.3.1 or later: The fix corrects octal interpretation and closes the parsing inconsistency. If your project depends on ip-address, update immediately if you're on 10.2.0 or earlier.

  • Test IP parsing against real resolvers: Don't assume your library matches DNS behavior. Write tests that compare your parser's output to actual DNS resolution for edge cases like leading-zero octets.

  • IP-based security requires consistency across the stack: Whether you're validating whitelists, parsing proxy headers, or constructing internal URLs, ensure all components (application code, libraries, DNS, OS) interpret IP addresses the same way.


How Orbis AppSec Detected This

Source: Dependency manifest (plugins/canvasight/package-lock.json) containing ip-address version 10.2.0

Sink: Any code path in the CanvaLight plugin that uses Address4 to parse IP addresses for validation, filtering, or access control decisions

Missing Control: The ip-address 10.2.0 library lacked proper octal interpretation for leading-zero octets, creating a divergence from standard resolver behavior

CWE: CWE-1025 (Comparison Using Wrong Factors) and CWE-436 (Interpretation Conflict)

Fix: Upgrade ip-address from 10.2.0 to 10.3.1 to correct the Address4 parser's handling of leading-zero octets, aligning it with RFC standards and DNS resolver behavior

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.


Conclusion

CVE-2026-69192 demonstrates a subtle but critical class of vulnerabilities: semantic divergence between components that should agree on data interpretation. When an application's IP parser and a DNS resolver interpret the same IP string differently, attackers can exploit the gap to bypass security controls and execute SSRF attacks.

The fix—upgrading ip-address to 10.3.1—restores consistency by correcting octal interpretation. However, the broader lesson is clear: always verify that your security-critical libraries match the behavior of the systems they interact with. For IP addresses, this means testing against real DNS resolvers. For other data types (URLs, file paths, JSON), the principle remains the same.

By keeping dependencies updated, validating parsing consistency, and combining IP-based controls with cryptographic authentication, you can prevent similar vulnerabilities in your own code.


Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #3

Related Articles

high

Meta.get() Honored @uploadURL From Script Headers: SSRF Fix

A userscript manager's metadata parser accepted the `@uploadURL` directive from a script's own header block, so any installed or auto-updated script could silently redirect the options-page `uploadScript()` fetch to an attacker-chosen destination — including loopback, link-local metadata endpoints, and LAN addresses. The fix makes `Meta.get()` ignore `@uploadURL` when it appears in a script header, leaving the User Metadata field (validated in `Meta.getUserMeta()`) as the only way to set it, and

high

Unvalidated thumbnailUrl Passed to axios.get(): SSRF Risk

A server-side image helper passes a `thumbnailUrl` value — sourced from 3D-print file metadata returned by an OctoPrint instance — straight into `axios.get()` with no scheme, host, or IP validation. Anyone who can write that metadata (a crafted G-code file, or a compromised/spoofed OctoPrint endpoint) turns the application into an HTTP proxy for internal networks and cloud metadata services. The accompanying pull request bumps `react-router-dom` from 7.9.1 to 7.18.4 to pick up the CVE-2026-21884

high

esearch() SSRF: requests.get() Trusted Any Host in the URL

A citation format-conversion script used by an AI research skill built HTTP URLs from user-supplied PMIDs, DOIs, arXiv IDs, and free-text queries, then passed the resulting string straight to `requests.get()` with no check that it still pointed at an intended API host. The fix introduces an `ALLOWED_HOSTS` set containing the three real upstream APIs and an `_is_allowed_url()` helper that compares `urlparse(url).hostname` against it before the request is issued. This closes a CWE-918 server-side

high

updateCardBg() Follows Unvalidated 302 Location Headers

A background-image updater fetched a configured image URL with manual redirect handling and then re-issued the request to whatever `Location` header came back, with no scheme or host checks. A redirect to `http://169.254.169.254/` or `http://127.0.0.1:<port>/` would have been followed with the original fetch options attached, and the response body written to disk as an image asset. The fix resolves the redirect target against `imgDownloadUrl` and rejects anything that is not HTTPS on the same ho

high

stream_media_file SSRF: src Parameter Reaches requests.get()

A media-download helper accepted a fully attacker-controlled URL from the `src` query parameter and passed it straight to `requests.get()`, turning the service into an open HTTP proxy for internal networks and cloud metadata endpoints. The fix introduces an `assert_safe_url()` guard that resolves the hostname with `getaddrinfo()` and rejects private, loopback, link-local, reserved, and multicast addresses before any request is issued. The guard is now called at the top of both `download_media_fi

high

ip-address 10.2.0 SSRF: Inconsistent Parsing Bypasses IP Checks

The `ip-address` npm package version 10.2.0 contains an inconsistent parsing vulnerability that allows attackers to bypass IP-based access controls. By representing IPv4 addresses in IPv4-mapped IPv6 notation, attackers can trick applications into allowing requests to blocked internal addresses. Upgrading to 10.3.1 resolves this through stricter address normalization.