Skip to content

fix(scripts): opt fixture capture out of Node's Happy-Eyeballs connect#6505

Merged
JSONbored merged 1 commit into
mainfrom
fix/capture-fixtures-happy-eyeballs
Jul 17, 2026
Merged

fix(scripts): opt fixture capture out of Node's Happy-Eyeballs connect#6505
JSONbored merged 1 commit into
mainfrom
fix/capture-fixtures-happy-eyeballs

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • scripts/capture-fixtures.mjs's DNS-pinning lookup callback (SSRF/rebinding guard) only supports the old single-address dns.lookup callback signature.
  • Node's Happy-Eyeballs dual-stack connect path (autoSelectFamily, default-on since Node 20+) calls custom lookup callbacks with { all: true } and expects an array back -- this callback returns a scalar, so every request threw TypeError [ERR_INVALID_IP_ADDRESS]: Invalid IP address: undefined.
  • Result in production: 0/598 fixtures captured, capture-failed on 100% of candidates, which also broke get_fixture/get_api_schema downstream (both REST and MCP).
  • The sibling safeFetch helper in scripts/lib.mjs (used by snapshot-openapi.mjs and others) was unaffected -- it goes through undici's Agent/dispatcher, not node:http's raw lookup option, and its createPinnedLookup already handles both callback shapes.
  • Fix: autoSelectFamily: false on the request options -- this pinned single-address lookup never needed the multi-attempt path.

Found during a full data-source audit following D1 retirement (unrelated to D1 -- pure Node runtime-behavior regression).

Test plan

  • Reproduced the exact TypeError locally against a known-healthy target (apex.api.macrocosmos.ai)
  • Confirmed autoSelectFamily: false resolves it against the same target
  • node scripts/capture-fixtures.mjs --dry-run: went from 0/590 (0%) to ~420/590 (~72%) captured; all remaining failures are legitimate (429 rate limits, non-JSON content-type, real 404/422/502/503, oversized bodies, genuine timeouts) -- zero TypeErrors remain
  • npx eslint / npx prettier --check clean

capture-fixtures.mjs pins DNS resolution by passing a custom `lookup`
callback straight to node:http/https's request options (SSRF/rebinding
guard). Node's dual-stack Happy-Eyeballs connect path (autoSelectFamily,
default-on since Node 20+) calls that callback with `{ all: true }` and
expects an array back; this callback only ever returns a single scalar
address, so the multi-connect path threw "Invalid IP address: undefined"
on every single request -- 0/598 fixtures captured in production.

Confirmed live: reproduced the exact TypeError against a known-healthy
target, fixed by disabling autoSelectFamily (this pinned single-address
lookup was never using the multi-attempt path anyway), verified the
same target then succeeds and a full dry-run run goes from 0% to ~72%
captured (remaining failures are legitimate: rate limits, non-JSON
content types, real upstream errors).
@superagent-security

Copy link
Copy Markdown

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.85%. Comparing base (632d986) to head (4232ec0).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6505   +/-   ##
=======================================
  Coverage   97.85%   97.85%           
=======================================
  Files         174      174           
  Lines       22196    22196           
  Branches     8798     8798           
=======================================
  Hits        21721    21721           
  Misses         81       81           
  Partials      394      394           
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JSONbored
JSONbored merged commit ff38590 into main Jul 17, 2026
13 checks passed
@JSONbored
JSONbored deleted the fix/capture-fixtures-happy-eyeballs branch July 17, 2026 12:50
@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix or unsolicited PR — scores a 0.05x multiplier. label Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix or unsolicited PR — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant