Skip to content

feat: IPv6 support, OpenAPI 1.4.0 nested schema, frontend alignment - #20

Merged
jjesse merged 6 commits into
masterfrom
feature/openapi-ipv6-private-ip
Aug 1, 2026
Merged

jjesse merged 6 commits into
masterfrom
feature/openapi-ipv6-private-ip

Conversation

@jjesse

@jjesse jjesse commented Aug 1, 2026

Copy link
Copy Markdown
Owner

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 geolocation
  • Frontend dual-stack validation and input sanitization

API / OpenAPI

  • openapi.yaml v1.4.0 with nested DatacenterInfo schema
  • Trace response documented as results[] / totalResults / foundResults
  • ZDX userpath response matches actual { success, data: { ... } } shape

Frontend fixes

  • showSuccess reads nested datacenter object (was broken against API)
  • Trace UI normalizes results → hops display shape

Python / docs

  • zdx_oneapi_geopath.py — full RFC 1918 172.16.0.0/12 + IPv6 private ranges; except Exception
  • requirements.txt
  • README / TODO / CHANGELOG / README_PYTHON updates (TRUST_PROXY, OneAPI section, nested response example)

After merge

  • Tag v1.4.0 once CI is green on master
  • Optional follow-ups: cache stampede protection, input length guards, health version field

jjesse and others added 6 commits July 31, 2026 23:38
- 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
@jjesse
jjesse marked this pull request as ready for review August 1, 2026 04:05
Copilot AI review requested due to automatic review settings August 1, 2026 04:05
@jjesse
jjesse merged commit 46f966b into master Aug 1, 2026
2 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.js and wire family-aware matching + expanded private/link-local handling in server.js.
  • Align frontend rendering/trace normalization with nested datacenter objects 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 thread utils/ip.js
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 thread server.js
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 thread zdx_oneapi_geopath.py
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 thread openapi.yaml
Comment on lines 355 to 357
datacenter:
type: string
$ref: '#/components/schemas/DatacenterInfo'
nullable: true
Comment thread public/app.js
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 thread tests/unit/ip.test.js
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 thread CHANGELOG.md
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).
Comment thread openapi.yaml
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
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