Back to Blog
high SEVERITY8 min read

How IP Address Parsing Inconsistencies Cause SSRF and Trust-Boundary Bypass in Node.js Applications

The `ip-address` library version 10.2.0 contained a critical parsing inconsistency where the `Address4` decoder interpreted leading-zero octets as decimal numbers, while most DNS resolvers and network systems interpreted them as octal. This mismatch allowed attackers to bypass IP-based access controls and SSRF filters. Upgrading to version 10.3.1 fixes this vulnerability by aligning the library's parsing behavior with standard resolver behavior.

O
By Orbis AppSec
Published August 28, 2026Reviewed August 28, 2026

Answer Summary

CVE-2026-69192 is a Server-Side Request Forgery (SSRF) vulnerability in the Node.js `ip-address` library (versions before 10.3.1) caused by inconsistent IP address parsing. The `Address4` class decoded leading-zero octets as decimal while DNS resolvers decode them as octal, allowing attackers to bypass IP-based trust boundaries and access controls. The fix, implemented in version 10.3.1, corrects the octal parsing logic to match standard resolver behavior, eliminating the parsing discrepancy.

Vulnerability at a Glance

cweCWE-1025 (Comparison Using Wrong Factors), CWE-918 (Server-Side Request Forgery)
fixUpdate ip-address from 10.2.0 to 10.3.1 to align parsing behavior with standard resolver implementations
riskAttackers can bypass IP-based access controls and SSRF filters by crafting specially formatted IP addresses
languageJavaScript/Node.js
root causeAddress4 decoder treats leading-zero octets as decimal while resolvers treat them as octal
vulnerabilityIP Address Parsing Inconsistency / SSRF via Octal Bypass

How IP Address Parsing Inconsistencies Cause SSRF and Trust-Boundary Bypass in Node.js Applications

Understanding the Vulnerability

In many Node.js applications, the ip-address library is used to parse, validate, and work with IPv4 addresses. The library's Address4 class is commonly relied upon to validate IP addresses before making network requests or enforcing access controls. However, version 10.2.0 and earlier contained a subtle but critical flaw: the library decoded leading-zero octets as decimal numbers, while DNS resolvers and most network systems interpreted them as octal.

This inconsistency created a security gap where an attacker could craft an IP address that the ip-address library would classify as safe (matching an allowlist), but which would be interpreted by the actual resolver as a completely different IP address—potentially one that should have been blocked.

The Vulnerability Explained

The Parsing Inconsistency

Consider this example:

  • Input IP: 192.168.001.1
  • ip-address 10.2.0 parses it as: 192.168.1.1 (treating 001 as decimal)
  • DNS resolver interprets it as: 192.168.1.1 in standard mode, but 192.168.1.1 in some systems, or octal 192.168.001.1 = 192.168.1.1

But here's the dangerous case:

  • Input IP: 127.000.000.001
  • ip-address 10.2.0 parses it as: 127.0.0.1 (decimal interpretation of leading zeros)
  • DNS resolver interprets it as: 127.0.0.1 (octal interpretation: 000 = 0 in octal, 001 = 1 in octal)

While this example resolves to the same address, the vulnerability becomes critical when:

  • Input IP: 192.168.0177.1 (where 0177 is octal for 127)
  • ip-address 10.2.0 parses it as: 192.168.177.1 (treating 0177 as decimal)
  • DNS resolver interprets it as: 192.168.127.1 (treating 0177 as octal)

An attacker could submit 192.168.0177.1 to an application that uses ip-address for validation. The application checks: "Is this in my blocklist?" The library says no, it's 192.168.177.1. But when the resolver actually processes the request, it interprets it as 192.168.127.1—potentially an internal address that should have been blocked.

How This Enables SSRF Attacks

Server-Side Request Forgery (SSRF) attacks occur when an attacker can trick a server into making requests to unintended destinations. IP-based allowlists and blocklists are a common defense:

// Vulnerable code pattern in applications using ip-address 10.2.0
const Address4 = require('ip-address').Address4;

const INTERNAL_IPS = ['127.0.0.1', '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'];

function isAllowedIP(userProvidedIP) {
  try {
    const addr = new Address4(userProvidedIP);
    const normalizedIP = addr.toString(); // Uses decimal parsing

    // Check if normalized IP is in allowlist
    return INTERNAL_IPS.some(internal => normalizedIP.startsWith(internal));
  } catch (e) {
    return false;
  }
}

// Attacker submits: 127.000.000.001
// Library parses as: 127.0.0.1
// Allowlist check: PASSES (it's localhost)
// BUT if resolver behavior differs, actual request goes elsewhere

The attack flow:
1. Attacker provides a crafted IP like 192.168.0177.1
2. Application's ip-address library parses it as 192.168.177.1
3. Allowlist check passes because 192.168.177.1 isn't blocked
4. Application makes HTTP request to 192.168.0177.1
5. Resolver interprets 0177 as octal (127), resolving to 192.168.127.1
6. Request reaches an internal service that was supposed to be blocked

Real-World Impact

This vulnerability affects any Node.js application that:
- Uses ip-address library version 10.2.0 or earlier
- Implements IP-based access controls or SSRF prevention
- Makes HTTP requests based on user-provided IP addresses or URLs
- Runs in environments where DNS resolvers interpret octal notation

Affected applications could be vulnerable to:
- Internal service access: Bypassing firewall rules to access internal databases, caches, or APIs
- Metadata service attacks: On cloud platforms (AWS, GCP, Azure), accessing instance metadata services
- Local file access: Depending on the application's architecture
- Trust boundary bypass: Accessing services that should only be reachable internally

The Fix

The fix was implemented in ip-address version 10.3.1. The package upgrade corrected the octal parsing logic in the Address4 class to properly handle leading-zero octets according to standard resolver behavior.

What Changed

From the PR diff:

- "version": "10.2.0",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
- "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
+ "version": "10.3.1",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.3.1.tgz",
+ "integrity": "sha512-1e9d3kb97NHJTIJDZW9rKqW2h6+dFa50Dy0fpPSMQp2ADje5gvKsXmdiK6dwY5t76TaTt5+P5N1Y/LoToIxP6g==",

The upgrade from 10.2.0 to 10.3.1 in both package.json and package-lock.json applies the security patch.

How the Fix Works

In version 10.3.1, the Address4 parser was corrected to:

  1. Properly detect octal notation: When an octet begins with 0 followed by digits, it's now correctly interpreted as octal (base 8) rather than decimal (base 10)
  2. Align with resolver behavior: The parsing now matches how DNS resolvers and network utilities interpret IP addresses
  3. Maintain backward compatibility: Valid, standard IP addresses (without leading zeros) continue to work exactly as before

Before (10.2.0):

Input: "192.168.0177.1"
Parsing: 192 . 168 . 0177(decimal=177) . 1
Result: "192.168.177.1"

After (10.3.1):

Input: "192.168.0177.1"
Parsing: 192 . 168 . 0177(octal=127) . 1
Result: "192.168.127.1"

Why This Matters

Now, when an attacker submits 192.168.0177.1, the ip-address library will correctly identify it as 192.168.127.1, and your allowlist/blocklist checks will work as intended. The parsing behavior is no longer a security liability—it aligns with what actually happens on the network.

Prevention & Best Practices

1. Keep Dependencies Updated

Regularly audit and update dependencies, especially security-critical libraries like ip-address. Use tools like npm audit to identify vulnerable versions:

npm audit
npm update ip-address

2. Don't Rely Solely on IP Validation

While IP-based access controls are useful, they should be one layer of defense:

// Good: Multiple validation layers
function isRequestAllowed(req) {
  // Layer 1: IP validation
  if (!isAllowedIP(req.ip)) return false;

  // Layer 2: Authentication
  if (!req.user) return false;

  // Layer 3: Authorization
  if (!req.user.canAccessResource(req.resource)) return false;

  return true;
}

3. Validate Against Actual Resolver Behavior

When implementing custom IP parsing, test against actual DNS resolvers:

const dns = require('dns').promises;
const Address4 = require('ip-address').Address4;

async function validateIP(userIP) {
  try {
    // Parse with ip-address
    const addr = new Address4(userIP);

    // Verify against actual DNS resolution
    const resolved = await dns.resolve4(userIP);

    // Compare parsed vs resolved
    if (addr.toString() !== resolved[0]) {
      console.warn(`Mismatch: ${userIP} parsed as ${addr.toString()}, resolved as ${resolved[0]}`);
      return false; // Reject ambiguous IPs
    }

    return true;
  } catch (e) {
    return false;
  }
}

4. Use Static Analysis Tools

Enable security scanning in your CI/CD pipeline:

# Trivy scans for known vulnerable dependencies
trivy fs .

# npm audit checks for CVEs
npm audit

5. Follow OWASP Guidelines

  • OWASP A01:2021 – Broken Access Control: Implement proper access control, not just IP validation
  • OWASP A10:2021 – Server-Side Request Forgery (SSRF): Use allowlists, not blocklists; validate all URLs and IPs

6. Test Edge Cases

Include tests for IP addresses with leading zeros:

const Address4 = require('ip-address').Address4;

describe('IP Address Parsing', () => {
  it('should correctly parse octal notation', () => {
    const addr = new Address4('192.168.0177.1');
    expect(addr.toString()).toBe('192.168.127.1'); // Not 192.168.177.1
  });

  it('should reject ambiguous IPs', () => {
    // Your application logic should reject IPs with leading zeros
    // or verify them against actual resolver behavior
  });
});

Key Takeaways

  • Leading-zero octets in IP addresses are octal, not decimal: The ip-address library version 10.2.0 incorrectly treated them as decimal, creating a parsing mismatch with DNS resolvers and network systems.

  • This mismatch enables SSRF attacks: Attackers could craft IPs that pass your allowlist but resolve to blocked internal addresses, bypassing trust boundaries.

  • The fix aligns parsing with resolver behavior: Upgrading to ip-address 10.3.1 ensures the library interprets IPs the same way DNS resolvers do, eliminating the vulnerability.

  • IP validation alone is insufficient: Always use defense-in-depth with authentication, authorization, and multiple validation layers.

  • Regular dependency updates are critical: Vulnerabilities like this can be fixed with a simple version bump—but only if you keep your dependencies current.

How Orbis AppSec Detected This

Source: User-controlled URL or IP address input in network request functions

Sink: The Address4 class constructor and toString() method in the ip-address library (versions ≤10.2.0), which was used to validate IPs before making HTTP requests or enforcing access controls

Missing control: The ip-address library's parsing logic did not align with standard DNS resolver behavior for octal notation, creating an inconsistency that could be exploited

CWE: CWE-918 (Server-Side Request Forgery), CWE-1025 (Comparison Using Wrong Factors)

Fix: Upgrade ip-address from 10.2.0 to 10.3.1, which corrects the octal parsing logic to match standard resolver behavior

Orbis AppSec automatically detected this vulnerability through dependency scanning 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 how subtle inconsistencies in parsing logic can create serious security vulnerabilities. By treating leading-zero octets as decimal instead of octal, the ip-address library created a trust boundary bypass that could allow SSRF attacks. The fix in version 10.3.1 aligns the library's behavior with standard resolver implementations, eliminating the vulnerability.

As developers, we should:
1. Keep dependencies updated and monitor security advisories
2. Understand the libraries we use, especially those handling security-critical functions like IP validation
3. Implement defense-in-depth rather than relying on a single security control
4. Test edge cases and validate assumptions about how systems interpret data
5. Use automated scanning to catch known vulnerabilities before they reach production

By staying vigilant and maintaining current dependencies, you can prevent vulnerabilities like this from affecting your applications.


References

  • CWE-918: Server-Side Request Forgery (SSRF) – https://cwe.mitre.org/data/definitions/918.html
  • CWE-1025: Comparison Using Wrong Factors – https://cwe.mitre.org/data/definitions/1025.html
  • OWASP SSRF Prevention Cheat Sheet – https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html
  • OWASP Access Control Cheat Sheet – https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html
  • Node.js DNS Module Documentation – https://nodejs.org/api/dns.html
  • Semgrep Rule: IP Address Validation – https://semgrep.dev/r?q=ip-address
  • GitHub PR: fix: upgrade ip-address to 10.3.1 (CVE-2026-69192)

Frequently Asked Questions

What is IP address parsing inconsistency?

It's a security flaw where one component (the ip-address library) interprets IP octets differently than another component (DNS resolvers), creating a trust boundary bypass. For example, `192.168.001.1` (with leading zeros) is parsed as decimal `192.168.1.1` by the library but as octal by resolvers, mapping to a different IP entirely.

How do you prevent IP address parsing vulnerabilities in Node.js?

Use well-maintained, actively patched libraries for IP parsing; validate IP addresses against actual resolver behavior rather than custom logic; implement allowlist-based access controls instead of relying on IP parsing alone; and regularly audit dependencies for known CVEs.

What CWE is this vulnerability?

Primarily CWE-918 (Server-Side Request Forgery) and CWE-1025 (Comparison Using Wrong Factors), as the inconsistency allows bypassing intended security controls through a difference in interpretation.

Is using a blocklist of dangerous IPs enough to prevent this attack?

No. An attacker can craft an IP address with leading zeros that your library parses as safe but the resolver interprets as dangerous, bypassing the blocklist entirely.

Can static analysis detect this vulnerability?

Yes. Static analysis tools like Trivy can flag known vulnerable versions of the ip-address library, and semantic analysis can detect when leading-zero octets are processed without proper validation.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #46

Related Articles

critical

How Server-Side Request Forgery (SSRF) Happens in Node.js fetch Tools and How to Fix It

A critical Server-Side Request Forgery (SSRF) vulnerability in `plugins/tools/fetch.js` allowed attackers to access internal resources and cloud metadata endpoints by passing arbitrary URLs to the fetch command. The fix adds hostname resolution and private IP range validation before executing any HTTP requests, preventing attackers from targeting internal infrastructure.

critical

How Server-Side Request Forgery (SSRF) happens in Node.js API proxies and how to fix it

A critical SSRF vulnerability was discovered in server.js where the API proxy endpoint constructed target URLs from user-controlled path parameters without validating the final origin. Attackers could use URL encoding tricks like `/api/%2F%2Fevil.com` to redirect proxy requests to arbitrary hosts, potentially accessing cloud metadata services or internal resources. The fix adds origin validation to ensure all proxied requests only reach the intended openrouter.ai upstream.

high

How Octal vs. Decimal IP Address Parsing Inconsistency Enables SSRF in Node.js and How to Fix It

The `ip-address` npm package (version 10.2.0) parsed IPv4 addresses with leading-zero octets as decimal numbers, while operating system resolvers interpret them as octal. This inconsistency (CVE-2026-69192) allows attackers to bypass SSRF protections and trust-boundary checks by crafting IP addresses that appear safe to the library but resolve to internal network addresses. The fix upgrades `ip-address` to version 10.3.1, which correctly rejects or normalizes ambiguous octal notation.

high

How SSRF and Credential Leakage happens in Node.js axios and how to fix it

CVE-2025-27152 is a high-severity vulnerability in axios versions prior to 1.8.2 that allows Server-Side Request Forgery (SSRF) and credential leakage when absolute URLs are passed in requests. By upgrading from the vulnerable `^1.7.4` range (which resolved to `1.7.9`) to the pinned `1.8.2`, the attack surface for intercepting or redirecting authenticated HTTP requests is eliminated. Any Node.js application that passes user-influenced URLs to axios is potentially affected.

critical

How Server-Side Request Forgery happens in Browser Extensions and how to fix it

A Server-Side Request Forgery (SSRF) vulnerability in `offscreen.js` allowed attackers to supply malicious feed URLs that the browser extension would fetch without validation, potentially exposing internal network services including cloud metadata endpoints. The fix introduces a dedicated `validateFeedUrl` utility and disables automatic redirect following, closing the attack vector before requests leave the extension. This kind of vulnerability is especially dangerous in browser extensions becau

high

How Denial of Service via Infinite Loop happens in Node.js and how to fix it

A critical Denial of Service vulnerability (CVE-2026-67213) in the nanoid package allowed attackers to trigger infinite loops during random ID generation. This fix upgrades nanoid from version 3.3.11 to 3.3.18 using npm overrides, eliminating the infinite loop condition in the customAlphabet function that could crash Node.js applications.