feat: IPv6 support, OpenAPI 1.4.0 nested schema, frontend alignment - #20
Merged
Merged
Conversation
- Dual-stack IP utilities (IPv4 + IPv6 CIDR matching via BigInt) - lookupIp no longer skips IPv6 CENR ranges - OpenAPI 1.4.0 matches nested datacenter response and trace results shape - Fix RFC 1918 172.16.0.0/12 coverage and bare except in zdx_oneapi_geopath.py - Frontend accepts IPv6 and renders nested datacenter objects - Docs: TODO, CHANGELOG, README, README_PYTHON, requirements.txt
…e-ip [WIP] Update IP handling and OpenAPI configuration
- server.js: match IPv6 CENR ranges by family; private IPv6 ULA/link-local handling - openapi.yaml: v1.4.0 nested datacenter + correct trace shape + dual-stack IPs - public/app.js: dual-stack validation, nested datacenter UI, normalize trace results - tests: IPv6 CIDR/range/validation coverage - docs: TODO/CHANGELOG/README/README_PYTHON; requirements.txt
Wire IPv6 through server, frontend, OpenAPI, tests, and docs. - server.js: family-aware CENR matching; IPv6 private/link-local geo skip - openapi.yaml v1.4.0: nested DatacenterInfo; correct trace/ZDX shapes - public/app.js: dual-stack validation; nested datacenter UI; results→hops - unit tests for IPv6 CIDR/range/validation - README/TODO/CHANGELOG/README_PYTHON updates
There was a problem hiding this comment.
Pull request overview
This PR updates the Zscaler datacenter lookup project to support dual-stack (IPv4/IPv6) lookups end-to-end, aligns the frontend with the API’s nested datacenter response shape, and updates OpenAPI/docs/Python tooling to match.
Changes:
- Add IPv6-capable CIDR parsing/range checks in
utils/ip.jsand wire family-aware matching + expanded private/link-local handling inserver.js. - Align frontend rendering/trace normalization with nested
datacenterobjects and updated trace response fields. - Update OpenAPI to v1.4.0 and refresh docs/Python packaging (
requirements.txt, README updates, changelog/todo status).
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
zdx_oneapi_geopath.py |
Expands private IP detection (IPv4 RFC1918 + IPv6) and narrows exception handling. |
utils/ip.js |
Implements IPv6 expansion/BigInt conversion, dual-stack CIDR parsing, and family helpers. |
TODO.md |
Marks IPv6/OpenAPI/docs/deps follow-ups as completed. |
tests/unit/ip.test.js |
Extends unit coverage to IPv6 parsing/validation and range matching. |
server.js |
Enables IPv6 CIDR matching and expands private/link-local geolocation skips; adds query-param type guards. |
requirements.txt |
Adds pinned-ish Python deps for the scripts. |
README.md |
Updates feature list, lookup response example (nested datacenter), and adds TRUST_PROXY docs. |
README_PYTHON.md |
Documents the OneAPI variant script usage and env vars. |
public/app.js |
Adds dual-stack input sanitization/validation and updates UI to nested response shape + trace normalization. |
openapi.yaml |
Bumps spec to 1.4.0 and updates schemas for nested datacenter + trace/userpath shapes. |
CHANGELOG.md |
Records IPv6/OpenAPI/docs/deps changes in Unreleased. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+200
to
+211
| function isValidIpv6(ip) { | ||
| if (ip === null || ip === undefined || typeof ip !== 'string' || ip === '') { | ||
| return false; | ||
| } | ||
|
|
||
| try { | ||
| expandIpv6(ip); | ||
| return true; | ||
| } catch { | ||
| return false; | ||
| } | ||
| } |
Comment on lines
+295
to
+299
| // IPv6 unique-local (fc00::/7) and link-local (fe80::/10) | ||
| const lower = ip.toLowerCase(); | ||
| if (lower.startsWith('fc') || lower.startsWith('fd') || lower.startsWith('fe80:')) { | ||
| return null; | ||
| } |
Comment on lines
+24
to
+27
| # IPv6 unique-local (fc00::/7) and link-local (fe80::/10) | ||
| lower = ip.lower() | ||
| if lower.startswith(("fc", "fd", "fe80:")): | ||
| return "Local Network" |
Comment on lines
355
to
357
| datacenter: | ||
| type: string | ||
| $ref: '#/components/schemas/DatacenterInfo' | ||
| nullable: true |
Comment on lines
+563
to
+565
| latitude: r.datacenter ? r.datacenter.latitude : (r.latitude || null), | ||
| longitude: r.datacenter ? r.datacenter.longitude : (r.longitude || null), | ||
| distanceFromPrevious: r.distanceFromPrevious || null |
Comment on lines
+231
to
+237
| test('returns false for invalid addresses', () => { | ||
| expect(isValidIpv6('')).toBe(false); | ||
| expect(isValidIpv6(null)).toBe(false); | ||
| expect(isValidIpv6('not-valid')).toBe(false); | ||
| // multiple :: is invalid | ||
| expect(isValidIpv6('::1::2')).toBe(false); | ||
| }); |
Comment on lines
49
to
+52
| ### Fixed | ||
| - SSRF vulnerability in `/api/zdx/userpath` endpoint by validating ZDX cloud parameter against allowlist (PR #4). | ||
| - Private-IP detection in `getIpGeolocation()` now covers IPv6 loopback (`::1`), IPv4 link-local (`169.254.x.x`), and IPv6 unique-local/link-local ranges in addition to existing RFC 1918 IPv4 ranges. | ||
| - Frontend `showSuccess()` now reads from the nested `data.datacenter` object returned by the API (was reading flat top-level fields). | ||
| - RFC 1918 private IP check now correctly identifies `172.16.0.0/12` range only (PR #5). |
| format: ipv4 | ||
| example: 165.225.28.50 | ||
| description: Zscaler datacenter IPv4 address to look up | ||
| description: Zscaler datacenter IPv4 or IPv6 address to look up |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings dual-stack IPv6 support, corrected OpenAPI schema, and frontend alignment to
master.PR #19 has been merged into this feature branch. This PR is ready to merge.
What's included
IPv6 end-to-end
utils/ip.js— full IPv4 + IPv6 CIDR parsing/matching (BigInt for v6)server.js— family-aware CENR matching (no longer skips IPv6 ranges); private IPv6 ULA/link-local handling in geolocationAPI / OpenAPI
openapi.yamlv1.4.0 with nestedDatacenterInfoschemaresults[]/totalResults/foundResults{ success, data: { ... } }shapeFrontend fixes
showSuccessreads nesteddatacenterobject (was broken against API)results→ hops display shapePython / docs
zdx_oneapi_geopath.py— full RFC 1918172.16.0.0/12+ IPv6 private ranges;except Exceptionrequirements.txtTRUST_PROXY, OneAPI section, nested response example)After merge
v1.4.0once CI is green on masterversionfield