fix: malformed http urls#11000
Conversation
There was a problem hiding this comment.
1 issue found and verified against the latest diff
Confidence score: 3/5
lib/utils.js’s prototype-chain walk can enter an infinite loop on craftedProxyobjects because there’s no cycle detection, which can hang execution or cause a denial-of-service path if untrusted objects reach this code — add visited-object tracking (or a max traversal depth) and a targeted test for cyclic/proxy chains before merging.
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
1 issue found across 4 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
|
@cubic-dev-ai please review in depth |
@jasonsaayman I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
3 issues found across 29 files
Confidence score: 3/5
- In
lib/adapters/fetch.js, the streammaxBodyLengthwrapping path ignoressupportsRequestStream, so environments without request stream support can still be handed aReadableStream, leading to request failures/regressions for streamed uploads—gate that wrapping logic onsupportsRequestStreambefore merging. - In
lib/utils.js(isSafeIterable), readingthing[Symbol.iterator]before pollution checks can still trigger pollutedObject.prototypeaccessors, which may throw or execute unintended code paths at runtime—move the safety checks ahead of property access (or use a safe lookup pattern) to de-risk this. - In
lib/helpers/shouldBypassProxy.js(isIPv6Unspecified), not recognizing compressed all-zero IPv6 forms can make equivalent unspecified addresses bypass proxy rules inconsistently, causing surprising networking behavior—normalize/expand IPv6 unspecified matching and add coverage for compressed variants.
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
The ERR_INVALID_URL error thrown for http:/https: URLs missing the "//" after the protocol (added in axios#11000) only said `Invalid URL: missing "//" after protocol`, with no indication of which value was rejected. Users upgrading to 1.18.0 hit this without a clear cause (axios#11008). Include the offending URL (in its control-character-normalized form) in the message, e.g. `Invalid URL "https:example.com": missing "//" after protocol`. Behavior is otherwise unchanged: the same inputs are still rejected with the same code. :surfer:
| const isSafeIterable = (thing) => | ||
| thing != null && hasOwnInPrototypeChain(thing, iterator) && isIterable(thing); | ||
|
|
There was a problem hiding this comment.
But an iterator is a function, obviously. How is the iterator method different from other built-in methods of the object prototype? Previously, we've already concluded that an attacker is not able to pollute an object's prototype with functions; otherwise, if an attacker can create a function using eval or new Function and inject it into the object's prototype as a method, then all these protections are completely meaningless.
Summary
Reject malformed
http:andhttps:URLs that omit//before adapter URL normalisation, returningAxiosErrorwithERR_INVALID_URLinstead of silently normalising invalid input.This also tightens related security coverage around polluted inherited config values, upload/content length limits, data URL size estimation, FormData recursion depth, and local proxy bypass matching.
Linked issue
Closes #7315
Changes
https:example.comandhttp:/example.comacross core URL building and adapters.formDataToJSON.0.0.0.0and IPv6::as local forNO_PROXYmatching.Checklist
index.d.tsandindex.d.cts) - N/A, no public API or type changeSummary by cubic
Reject malformed HTTP(S) URLs that omit “//” and harden stream/proxy safety. Size limits are now enforced consistently across
fetch, Node HTTP/HTTPS/HTTP2, and customfetch, and header/config reads ignore prototype pollution.Description
http:/https:URLs before adapter normalization; throwAxiosErrorERR_INVALID_URLand preserve config.utils.getSafeProp(auth, headers, params, serializer, proxy, method, agents, limits, timeouts, decompress); ignore values injected onObject.prototype.Symbol.iteratorfor header sources; only own iterators are used for request and response headers.maxBodyLengthon streamed uploads infetch, native HTTP/HTTPS, HTTP/2, and customfetch; never trust caller-declaredContent-Length. If theRequestimpl doesn’t support stream bodies, throwERR_NOT_SUPPORTinstead of forcing a stream.maxContentLengthon streamed responses with declared-length pre-checks; accept plain-object response headers viaAxiosHeaders.DEFAULT_FORM_DATA_MAX_DEPTH(100) and guard both{}metatokens andformDataToJSONpath parsing; throwERR_FORM_DATA_DEPTH_EXCEEDED.0.0.0.0and IPv6::(including compressed/all-zero forms) as local forNO_PROXY.data:URLs.data;getUriignores inherited serializer options.Docs
Please update
/docs/:http:/https:URLs missing//now throwERR_INVALID_URL.DEFAULT_FORM_DATA_MAX_DEPTH= 100) andERR_FORM_DATA_DEPTH_EXCEEDED.NO_PROXY(0.0.0.0,::) and consistent stream size enforcement;fetchthrowsERR_NOT_SUPPORTwhen itsRequestdoes not support stream bodies.Testing
fetch, Node HTTP/HTTP2, and XHR; config preserved.data;getUriignores inherited serializer options.Symbol.iteratorfor request/response headers; iterable sources must have own iterators.maxBodyLengthon streamed uploads acrossfetch, native HTTP/HTTPS, HTTP/2, and customfetch; declaredContent-Lengthcannot bypass limits; throwERR_NOT_SUPPORTwhenRequestlacks stream support.maxContentLengthon streamed responses with declared-length pre-checks; plain-object headers supported viaAxiosHeaders.{}metatokens andformDataToJSONparsing; throwsERR_FORM_DATA_DEPTH_EXCEEDED.data:URLs.NO_PROXYmatching for0.0.0.0and IPv6::(including compressed forms and ports).Semantic version impact
Patch: bug fixes and security hardening. Invalid inputs that were previously normalized now throw
ERR_INVALID_URL; no API changes.Written for commit d454282. Summary will update on new commits.