Hardening: input validation and bounds tightening across 36 subsystems (round 4) - #31339
Merged
Conversation
This was referenced May 25, 2026
This was referenced May 26, 2026
springmin
pushed a commit
to springmin/bun
that referenced
this pull request
May 26, 2026
* oven/main (10 new commits): Optimize TextEncoder.encode: restore SIMD ASCII fast paths lost in the Rust port (oven-sh#31385) js_parser: sanitize auto-generated default export name for digit-named modules (oven-sh#31403) fetch: run checkServerIdentity before writing the request (oven-sh#31325) ffi: avoid copying the threadsafe callback wrapper on the calling thread (oven-sh#31332) install: gate the exit-callback cache teardown to the main thread (oven-sh#31376) fix(node:module): don't register native helpers as their own constructors (oven-sh#31393) css: escape custom pseudo-class/element names when printing (oven-sh#31404) Deepen the lots-of-for-loop fixture so the transpiler stack-overflow tests throw on Windows (oven-sh#31382) Hardening: input validation and bounds tightening across 36 subsystems (round 4) (oven-sh#31339) Speed up FormData multipart serialization (oven-sh#31379) Auto-merged: src/install/PackageManager.rs, src/runtime/cli/upgrade_command.rs, src/runtime/webcore/Blob.rs, src/sys/lib.rs
Jarred-Sumner
added a commit
that referenced
this pull request
May 27, 2026
…s (round 6) (#31417) Tightens input validation, bounds checking, and state handling across the runtime, package manager, and CLI. Continuation of #31339; same structure (small per-area commits, regression tests included). ### Package manager / CLI - install: validate package folder names derived from dependency aliases before extraction (non-git resolutions) - install: require integrity for off-registry tarball URLs when migrating `package-lock.json` (yarn.lock migration unchanged — its v1 workspace/github entries legitimately omit integrity) - install: validate migrated git committish values as single path components - install: constrain transitive `file:` dependency targets to their declaring package - install: JSON-escape registry/git strings when saving `bun.lock`; escape quoted scalars in the yarn.lock printer - install: byte-compare string-pool hits in manifest parsing and bound version writes - install: key lifecycle-script trust on the declared dependency alias and resolution type - install: resolve bin link targets and skip entries that escape the package directory - install: bound cache-folder name formatting and tarball decompression output - bunx: re-validate cache directory ownership after creation - run: resolve the package-script shell from the original PATH instead of `node_modules/.bin` - upgrade-related items intentionally not included ### HTTP / TLS / networking - fetch: drop caller-supplied Transfer-Encoding for fixed-size bodies (single framing header on the wire) - fetch: exclude requests carrying custom TLS options from the experimental HTTP/3 path - node:http: validate `options.port` in ClientRequest (ERR_SOCKET_BAD_PORT) - node:http2: zero-fill outbound DATA frame padding - node:dns: reject hostnames containing embedded NUL bytes (slightly stricter than Node, which truncates at the NUL; never affects a valid hostname) - tls: re-establish per-loop BIO state before driving handshakes after JS callbacks - server: disarm request-body callbacks before handing the response to the file-stream path - server: restrict the development-mode `/bun:info` route to loopback clients - valkey: checkpoint partial-line scan progress; dev server: bound error-report path normalization - bun-vscode: bind the diagnostics socket to a fresh per-session path and verify it before advertising ### Web / runtime APIs - Blob/Body: copy content types into the Blob they describe; bound deserialization lengths; serialize only a slice's own window; tolerate odd-offset UTF-16 text decoding - S3: validate the `type` option with the same check other Blob constructors use - FormData: handle duplicate index-like field names in serialization - WebCrypto: refuse to serialize non-extractable CryptoKey material through script-visible serializers - node:crypto: fail closed on ECDH errors; stop after rejecting unsupported RSA decryption padding - node:fs: pin async write sources; bound recursive-readdir path joins - SQL: guard column-identifier tags when building row objects - escapeHTML: process lone surrogates without skipping the following character ### Parsers / shell / misc - shell: copy stdin redirect buffers up front; pin output redirect buffers; treat interpolated `cd` arguments literally - markdown: sanitize link/image/fence metadata in the ANSI renderer; make emphasis resolution linear on adversarial input - JSON5/JSONC: stack-checked AST conversion; YAML: bound merge-key materialization - CSS: clamp tokenizer advances at end of input; glob: derive entry offsets from the joined path - resolver: validate exports-map targets after wildcard substitution ### Tests 34 new regression tests across the touched areas, each verified to fail on the released build and pass here. A few fixes have no standalone test where the behavior difference is not observable from JS (noted per-commit in the shard history); CI exercises the affected suites. `cargo check` and cross-target checks pass on all 10 CI targets; the touched test suites pass locally with no new failures versus main. --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This was referenced May 29, 2026
This was referenced Jun 17, 2026
This was referenced Jul 7, 2026
robobun
added a commit
that referenced
this pull request
Jul 9, 2026
…ompat The Rust port of on_handshake (socket_body.rs) gained a bun_boringssl::check_server_identity() call in #31339 that the Zig reference (socket.zig onHandshake) never had. When the cert chain verifies but the peer cert's SAN/CN does not cover the connect hostname/servername, this flipped authorized to false, set a HOSTNAME_MISMATCH flag, and passed success=false to the JS handshake callback. Downstream effects: - tls.connect sets _secureEstablished = !!success, now false where Node and Bun 1.3.14 both report true - Bun.connect socket.authorized is now false where Zig returned true - socket.getAuthorizationError() returns an Error with the non-Node-standard code HOSTNAME_MISMATCH instead of null - a user-supplied options.checkServerIdentity that intentionally accepts the mismatch can no longer make _secureEstablished/success true Hostname verification is already performed in the JS layer (src/js/node/net.ts) via the user-overridable checkServerIdentity callback, which produces the Node-standard ERR_TLS_CERT_ALTNAME_INVALID. The native layer should report only the BoringSSL cert-chain verify result, matching the Zig reference. Revert on_handshake and get_authorization_error to match the Zig reference, drop the HOSTNAME_MISMATCH flag, and replace the test that locked in the divergent behavior with one asserting Zig/Node semantics. Add a node:tls test (verified against Node) that a user-supplied checkServerIdentity returning undefined yields _secureEstablished=true, authorized=true.
This was referenced Jul 16, 2026
This was referenced Jul 30, 2026
This was referenced Aug 13, 2026
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.
Continues the hardening series (rounds 1–3) with another pass of input validation, bounds checking, and lifetime tightening across the codebase. 73 changes, each in its own commit, plus regression tests covering 55 of them (each test verified to fail on the released bun and pass on this branch).
Areas touched: install / lockfile / tarball extraction / bunx / upgrade, sql (postgres, sqlite), tls / sockets / dns, http2 / http3 / http client / server, markdown, shell, node:fs / zlib / spawn / streams, crypto, vm, yaml / semver / valkey / undici / url / cookies, dev server, transpiler cache, string handling.
The general shape of the changes: reject malformed or out-of-range inputs earlier, bound buffer and recursion growth, keep borrowed buffers alive (or copy them) for the duration of the operations that read them, and validate names/paths/headers before they are used to address files, hosts, or memory.