fix: ctype UB, WebSocket over-read, stoi crash, signed shift UB, proto pollution - #65763
fix: ctype UB, WebSocket over-read, stoi crash, signed shift UB, proto pollution#65763VirajMishra1 wants to merge 1 commit into
Conversation
|
Review requested:
|
|
Caution AgentScan found account activity patterns that may be consistent with |
61336d0 to
ce98e53
Compare
|
Please make sure you have read and understood the following documents: |
|
I have read and understood all of the linked documents -- the contributing guide, pull request guide, AI use policy, automation policy, and Code of Conduct. To be transparent: I used AI tooling to help identify these bugs and draft the initial code, but I personally reviewed each change, understand what it does, and take responsibility for it. I did not use automated tooling to open this PR -- I opened it manually after reviewing the diff. Happy to discuss any of the specific changes if that would help. |
ce98e53 to
ab3faa4
Compare
|
Please check the CI failures for your PR. You can view them under https://github.com/nodejs/node/actions?query=actor%3AVirajMishra1+is%3Afailure You should make sure that your changes run successfully locally. See https://github.com/nodejs/node/blob/main/doc/contributing/pull-requests.md#step-6-test |
669354e to
9d651d8
Compare
|
Thanks for checking. Two CI failures, both now fixed:
Force-pushed the updated commit. CI should be clean now. |
9d651d8 to
3783f45
Compare
|
|
||
| const headersMap = this[kOutHeaders]; | ||
| const headers = {}; | ||
| const headers = { __proto__: null }; |
There was a problem hiding this comment.
this alone would likely need a full http CI benchmark
There was a problem hiding this comment.
I reverted it for now, happy to revisit in a separate PR with benchmarks.
- inspector_io.cc: cast isdigit arg to unsigned char (signed UB) - inspector_io.cc: replace stoi with from_chars (no-exceptions build) - inspector_io.cc: cast to unsigned int before left-shift (UB) - inspector_socket.cc: fix WebSocket frame bounds check Signed-off-by: VirajMishra1 <[email protected]>
3783f45 to
87a5ab0
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #65763 +/- ##
==========================================
+ Coverage 89.95% 90.05% +0.09%
==========================================
Files 757 769 +12
Lines 258053 261322 +3269
Branches 48934 49631 +697
==========================================
+ Hits 232144 235336 +3192
- Misses 16962 17035 +73
- Partials 8947 8951 +4
🚀 New features to boost your workflow:
|
MikeMcC399
left a comment
There was a problem hiding this comment.
The description in the body of the PR and the details in the title of the PR no longer correspond to the contents of the attached commit.
fix: ctype UB, WebSocket over-read, stoi crash, shift UB, proto pollution
Six correctness and safety fixes across four files:
1. src/inspector_io.cc:381 -- isdigit called on plain char (undefined behavior)
::isdigitis defined only for values representable as unsigned char or EOF.Passing a plain char (which may be negative on platforms where char is signed)
is undefined behavior. Fixed with an (unsigned char) cast in the lambda.
2. src/inspector_socket.cc:363 -- WebSocket extended-frame buffer over-read
The extended-payload-length bounds check used
buffer.size() - kMaskingKeyWidthInBytesas the minimum remaining bytes, but
bufferis the full original buffer whileitmay already have advanced into it. On a crafted extended-length frame,payload_lengthbytes could be read past the end of the available data.Fixed to check
buffer.end() - it(remaining bytes from current position).3. src/inspector_io.cc:383 -- std::stoi throws on out-of-range port strings
std::stoithrowsstd::out_of_rangefor digit-only strings that exceed INT_MAX(e.g. "99999999999" passes the isdigit check but crashes). Added
try/catch (std::exception&)to handle bothinvalid_argumentandout_of_range.4. src/inspector_io.cc:386 -- signed left shift is undefined behavior
target_session_id << 16on a signed int is UB if the result overflows.Fixed with
static_cast<unsigned int>(target_session_id) << 16.5. lib/_http_outgoing.js:287 -- prototype-inheriting header dict
const headers = {}in_renderHeaders()creates an object that inheritsfrom Object.prototype. Header names are user-controlled strings; a header named
__proto__ortoStringcan shadow prototype properties.Fixed to
{ __proto__: null }.6. lib/os.js:219 -- prototype-inheriting network interface dict
Same issue in
networkInterfaces(): the result object is keyed by OS interfacenames. Fixed to
{ __proto__: null }.