Skip to content

fix(assertString): throw typeError on objects with constructor and name property#2692

Open
newtondividedbysqm wants to merge 2 commits intovalidatorjs:masterfrom
newtondividedbysqm:patch-1
Open

fix(assertString): throw typeError on objects with constructor and name property#2692
newtondividedbysqm wants to merge 2 commits intovalidatorjs:masterfrom
newtondividedbysqm:patch-1

Conversation

@newtondividedbysqm
Copy link
Copy Markdown

assertString is currently validating objects with constructor property like {constructor: {name: "String"}}

@newtondividedbysqm newtondividedbysqm marked this pull request as ready for review March 30, 2026 18:42
@rubiin rubiin requested a review from Copilot March 30, 2026 19:05
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates assertString to correctly reject non-string objects that spoof constructor.name as "String", and expands tests to cover the spoofing cases (and boxed strings).

Changes:

  • Tighten assertString type checking to allow primitives/boxed strings while rejecting constructor-name spoofed objects.
  • Add unit tests for spoofed { constructor: { name: "String" } } inputs.
  • Add a unit test ensuring boxed strings (new String(...)) are accepted.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/lib/util/assertString.js Reworks the validation logic to avoid constructor-name spoofing.
test/util.test.js Adds regression tests for spoofed objects and boxed strings.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

export default function assertString(input) {
if (input === undefined || input === null) throw new TypeError(`Expected a string but received a ${input}`);
if (input.constructor.name !== 'String') throw new TypeError(`Expected a string but received a ${input.constructor.name}`);
if (typeof input !== 'string' && !(input instanceof String)) throw new TypeError(`Expected a string but received a ${input?.constructor?.name ?? typeof input}`)
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instanceof String will return false for boxed strings created in a different JS realm (e.g., iframe/window), which can cause valid String objects to be rejected. To avoid that cross-realm pitfall while still blocking { constructor: { name: 'String' } } spoofing, consider checking Object.prototype.toString.call(input) === '[object String]' (or reusing the existing typeOf util) alongside the primitive typeof input === 'string' check.

Suggested change
if (typeof input !== 'string' && !(input instanceof String)) throw new TypeError(`Expected a string but received a ${input?.constructor?.name ?? typeof input}`)
if (typeof input !== 'string' && Object.prototype.toString.call(input) !== '[object String]') throw new TypeError(`Expected a string but received a ${input?.constructor?.name ?? typeof input}`)

Copilot uses AI. Check for mistakes.
export default function assertString(input) {
if (input === undefined || input === null) throw new TypeError(`Expected a string but received a ${input}`);
if (input.constructor.name !== 'String') throw new TypeError(`Expected a string but received a ${input.constructor.name}`);
if (typeof input !== 'string' && !(input instanceof String)) throw new TypeError(`Expected a string but received a ${input?.constructor?.name ?? typeof input}`)
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing semicolon at the end of this throw statement will fail the repo's ESLint (airbnb-base defaults to semi: always). Add a trailing semicolon (and keep statement formatting consistent with the previous line).

Suggested change
if (typeof input !== 'string' && !(input instanceof String)) throw new TypeError(`Expected a string but received a ${input?.constructor?.name ?? typeof input}`)
if (typeof input !== 'string' && !(input instanceof String)) throw new TypeError(`Expected a string but received a ${input?.constructor?.name ?? typeof input}`);

Copilot uses AI. Check for mistakes.
Comment on lines +58 to +62
assert.throws(() => { assertString({constructor: {name: "string"}}); }, TypeError);
});

it('Should throw an error if argument provided is an Object pretending to be a \'String\'', () => {
assert.throws(() => { assertString({constructor: {name: "String"}}); }, TypeError);
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These new test inputs use double quotes ("string", "String") while the surrounding tests consistently use single quotes, and the repo ESLint config extends airbnb-base (default quotes: single). Switching these to single quotes will prevent lint failures.

Suggested change
assert.throws(() => { assertString({constructor: {name: "string"}}); }, TypeError);
});
it('Should throw an error if argument provided is an Object pretending to be a \'String\'', () => {
assert.throws(() => { assertString({constructor: {name: "String"}}); }, TypeError);
assert.throws(() => { assertString({constructor: {name: 'string'}}); }, TypeError);
});
it('Should throw an error if argument provided is an Object pretending to be a \'String\'', () => {
assert.throws(() => { assertString({constructor: {name: 'String'}}); }, TypeError);

Copilot uses AI. Check for mistakes.
assert.doesNotThrow(() => { assertString(''); });
});

Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This blank line contains trailing whitespace, which will fail no-trailing-spaces under airbnb-base ESLint. Remove the spaces so the line is truly empty.

Suggested change

Copilot uses AI. Check for mistakes.
@WikiRik
Copy link
Copy Markdown
Member

WikiRik commented Apr 1, 2026

Please fix the tests and look through the Copilot comments before we review this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants