Skip to content

[pull] main from yahoo:main - #1

Open
pull[bot] wants to merge 41 commits into
AimWhy:mainfrom
yahoo:main
Open

pull[bot] wants to merge 41 commits into
AimWhy:mainfrom
yahoo:main

Conversation

@pull

@pull pull Bot commented Jan 9, 2024 •

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot]

Can you help keep this open source service alive? 💖 Please sponsor : )

mkanyar and others added 6 commits January 8, 2024 15:35
Co-authored-by: Mike Stephane <[email protected]>
v6.0.0 introduced URL support, this PR updates the readme to document that change.
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.10.1 to 7.23.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.7/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@pull pull Bot added the ⤵️ pull label Jan 9, 2024
dependabot Bot and others added 23 commits April 1, 2024 15:21
… threads (#200)

* Add warning about using this for worker threads

* Referenceify links
* ci: setup trusted publishing workflow

* fix: .
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.21 to 4.17.23.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](lodash/lodash@4.17.21...4.17.23)

---
updated-dependencies:
- dependency-name: lodash
  dependency-version: 4.17.23
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ng (#207)

* fix(CVE-2020-7660): fix for RegExp.flags and  Date.prototype.toISOString

* fix: add v
okuryu and others added 12 commits March 25, 2026 23:23
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.23 to 4.18.1.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](lodash/lodash@4.17.23...4.18.1)

---
updated-dependencies:
- dependency-name: lodash
  dependency-version: 4.18.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Validates that URL.toString() returns a primitive string before
passing to serialize(), preventing code injection via Object.create(URL.prototype)
spoofing. Adds a regression test covering the attack vector from PSECBUGS-108653.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
PR-URL: #217
A fake RegExp created via Object.create(RegExp.prototype) passes
instanceof RegExp but can supply an object as .source. That object
survives serialize() as executable JS and runs when the consumer
evaluates new RegExp(obj, flags) via toString() coercion. Guard
mirrors the existing URL fix: assert typeof source === 'string'
and throw TypeError otherwise.

Fixes: PSECBUGS-112938
Fixes: PSECBUGS-108887
PR-URL: #222
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
The existing escapeFunctionBody() only escaped a complete `</script...>`
tag when it appeared within a single serialized value, allowing the tag
to be split across two separately-serialized function bodies to bypass
the escaping (each half missing either the `</script` prefix or the
closing `>`).

- SCRIPT_CLOSE_REGEXP now also matches a bare `</script` prefix followed
  by any WHATWG HTML tokenizer delimiter (TAB, LF, FF, CR, SPACE, `/`,
  `>`), so it's escaped even without a closing `>` in the same value.
- Escaping is lexically aware: string/template/regex literals and
  comments are scanned up front so their contents are still
  unicode-escaped, while `<`/`/` in plain code (comparison operators,
  regex delimiters, division) get a whitespace-insertion instead to
  avoid producing invalid JavaScript syntax.
- Span classification uses a single forward cursor for O(n) performance
  instead of a per-match linear scan.

Verified against parse5 (real HTML5 tokenizer), eval-based round-trip
tests for edge cases (String.raw, regex literals with quotes/character
classes, operator vs. regex-literal ambiguity), and the full test suite
(93/93 passing).

Refs: #220
PR-URL: #226
Co-authored-by: Copilot App <[email protected]>
* fix: prevent script close tag from being swallowed by a single match

`SCRIPT_CLOSE_REGEXP` matched `<\/script[^>]*>`, whose wildcard could run
from one `</script` to the next `>` anywhere in the function source. When a
second, complete `</script>` fell inside that span, the whole thing collapsed
into one match, and since the plain-code branch neutralizes only the leading
`<`, the swallowed tag was re-emitted verbatim.

A function body reaches that shape whenever `</script` appears in code
position -- `x</script=+/` parses as `x < /script=+/`, a comparison against a
regex literal -- followed by a `</script>` in a later string. The serialized
output then carries a live `</script>`, which terminates the script element
when embedded the way the README documents, so the rest of the payload is
parsed as HTML. Confirmed in headless Chromium: the injected `onerror` runs.

This regressed in v7.1.0. v7.0.7 used the same wildcard but escaped the
entire match, so nothing survived.

Excluding `<` from the character class fixes it: a match can no longer reach
past a second `<`, so every `</script` in the source either starts its own
match or is followed by a non-delimiter -- and the HTML tokenizer only ends
the tag name on TAB, LF, FF, CR, SPACE, `/` or `>`, emitting anything else as
text.

Co-Authored-By: Claude Opus 5 <[email protected]>

* fix: reject spoofed function toString() and make native-code check stateless

Two defects in `serializeFunc`, found while investigating the script close
tag escaping.

`fn.toString()` was trusted to return a string. It is attacker-controlled in
the same way `URL.prototype.toString` and `RegExp.prototype.source` were
before they were hardened. Returning an object with its own `replace()` is
enough to defeat the escaping outright, because `escapeFunctionBody()` is
built entirely from `str.replace(...)` calls -- the object's `replace` simply
returns itself, and the payload reaches the output untouched:

    var f = function () {};
    f.toString = () => ({
        replace: function () { return this; },
        toString: () => 'function(){}</script><img src=x onerror=alert(1)>'
    });
    serialize({ f: f });
    // {"f":function(){}</script><img src=x onerror=alert(1)>}

A primitive string from a spoofed `toString()` was already safe; only the
non-string case bypasses escaping. Rejecting it matches how the URL and
RegExp spoofing cases are already handled.

Separately, `IS_NATIVE_CODE_REGEXP` carried a `/g` flag. `.test()` on a
global regexp advances `lastIndex`, so after one rejection the next call
began its scan past the `[native code]` match and returned false, letting
every other native function through:

    try { serialize(Math.max); } catch (e) {}  // correctly throws
    serialize(Math.min);                       // 'function min() { [native code] }'

That output is a syntax error rather than an injection, so the impact is
limited to an unreliable guard, but the flag serves no purpose here.

Co-Authored-By: Claude Opus 5 <[email protected]>

---------

Co-authored-by: Claude Opus 5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants