Background
PR #6 (Add adsb.lol network feed capability) includes custom IP address validation code for SSRF protection. This code uses regex patterns to identify private and reserved IP ranges.
Current implementation:
Custom isPrivateIP() function in src/server.js (lines 31-69)
Regex-based validation for IPv4 and IPv6 private ranges
Handles IPv4-mapped IPv6 addresses
Zero runtime dependencies
Relevant code:
function isPrivateIP ( ip ) {
const ipv4PrivateRanges = [
/ ^ 1 2 7 \. / , / ^ 1 0 \. / , / ^ 1 7 2 \. ( 1 [ 6 - 9 ] | 2 [ 0 - 9 ] | 3 [ 0 - 1 ] ) \. / ,
/ ^ 1 9 2 \. 1 6 8 \. / , / ^ 1 6 9 \. 2 5 4 \. / , / ^ 0 \. 0 \. 0 \. 0 $ / ,
] ;
const ipv6PrivateRanges = [
/ ^ : : 1 $ / , / ^ f e 8 0 : / i, / ^ f c 0 0 : / i, / ^ f d 0 0 : / i, / ^ f f 0 0 : / i, / ^ : : f f f f : / i,
] ;
// ... validation logic
}
The Tradeoff
Zero Dependencies (Current):
✅ No supply chain attack risk
✅ Smaller Docker image
✅ Faster deployments (no npm registry dependency)
✅ No dependency vulnerabilities
❌ Security expertise needed to avoid bypasses
❌ May miss edge cases
❌ More maintenance burden
External Library (ipaddr.js):
✅ Battle-tested by thousands of projects
✅ Handles all edge cases (decimal notation, octal, hex, etc.)
✅ Security experts have reviewed it
✅ Actively maintained
❌ Adds 1 runtime dependency (~1.9KB)
❌ Supply chain risk (minimal for well-established library)
❌ Need to monitor for updates
Recommended Library: ipaddr.js
Why ipaddr.js:
No known SSRF bypass vulnerabilities (unlike ip, private-ip, nossrf)
Small footprint (1.9KB minified + gzipped)
Correct classification of reserved/private ranges
Used by Express.js and other major projects
Active maintenance
Usage example:
import ipaddr from 'ipaddr.js' ;
function isPrivateIP ( ip ) {
try {
const addr = ipaddr . process ( ip ) ;
return addr . range ( ) !== 'unicast' ; // Anything non-public
} catch {
return true ; // Invalid IP, block it
}
}
Edge Cases Our Code May Miss
Decimal IP notation : 2130706433 = 127.0.0.1
Octal notation : 0177.0.0.1 = 127.0.0.1
Hex notation : 0x7f.0.0.1 = 127.0.0.1
Mixed notation : 127.1 = 127.0.0.1
IPv6 zone IDs : fe80::1%eth0
IPv6 compressed forms : Various compression patterns
URL encoding : %3A%3A1 (encoded ::1)
Some of these are already blocked by our numeric format check, but a library provides comprehensive coverage.
Decision Framework
Consider the library if:
Security is critical (SSRF protection is security-critical ✓)
The code may be internet-facing (possible ✓)
Edge cases exist that could be missed (yes ✓)
Maintenance burden is a concern (small team ✓)
Keep custom code if:
Zero dependencies is a hard requirement (currently valued)
The code is simple and well-tested (moderately complex)
Performance is critical (not a bottleneck here)
You have security expertise in-house (unknown)
Recommendation
Add ipaddr.js as the single runtime dependency because:
SSRF protection is security-critical
The custom regex approach required 5+ iterations to get right in PR Add adsb.lol network feed capability #6
Going from 0→1 dependency is different than 1→many
1.9KB is negligible on Raspberry Pi 5
The security benefits outweigh the dependency cost
This maintains the "minimal dependencies" philosophy while using proven code for the one security-critical component.
Implementation (if approved)
Files to modify:
package.json: Add "ipaddr.js": "^2.2.0" to dependencies
src/server.js: Replace isPrivateIP() function with ipaddr.js implementation
test/server.test.js: Update tests to cover edge cases
Estimated effort: 1-2 hours
Alternative: Keep Current Implementation
If the decision is to maintain zero dependencies, consider:
Adding comprehensive test cases for edge case IP formats
Documenting known limitations
Security audit of the validation logic
Regular review of SSRF bypass techniques
References
Label suggestions: enhancement, security, dependencies, needs-decision
Background
PR #6 (Add adsb.lol network feed capability) includes custom IP address validation code for SSRF protection. This code uses regex patterns to identify private and reserved IP ranges.
Current implementation:
isPrivateIP()function insrc/server.js(lines 31-69)Relevant code:
The Tradeoff
Zero Dependencies (Current):
External Library (ipaddr.js):
Recommended Library: ipaddr.js
Why ipaddr.js:
ip,private-ip,nossrf)Usage example:
Edge Cases Our Code May Miss
2130706433=127.0.0.10177.0.0.1=127.0.0.10x7f.0.0.1=127.0.0.1127.1=127.0.0.1fe80::1%eth0%3A%3A1(encoded::1)Some of these are already blocked by our numeric format check, but a library provides comprehensive coverage.
Decision Framework
Consider the library if:
Keep custom code if:
Recommendation
Add ipaddr.js as the single runtime dependency because:
This maintains the "minimal dependencies" philosophy while using proven code for the one security-critical component.
Implementation (if approved)
Files to modify:
package.json: Add"ipaddr.js": "^2.2.0"to dependenciessrc/server.js: ReplaceisPrivateIP()function with ipaddr.js implementationtest/server.test.js: Update tests to cover edge casesEstimated effort: 1-2 hours
Alternative: Keep Current Implementation
If the decision is to maintain zero dependencies, consider:
References
Label suggestions: enhancement, security, dependencies, needs-decision