Summary
require-parseInt-radix short-circuits on argument count alone:
// require-parseInt-radix.ts:62
if (node.arguments.length >= 2) {
return;
}
This treats any second argument as a valid radix. But several second-argument values still trigger the exact implicit base detection the rule exists to prevent:
parseInt(str, 0) — radix 0 is spec-equivalent to no radix: a leading 0x/0X is parsed as hexadecimal.
parseInt(str, undefined) — same as omitting the radix.
parseInt(str, someVar) where someVar is 0/undefined/non-numeric at runtime — not statically a literal 10, so the safety claim is unverified.
All of these currently pass the rule silently, so parseInt(userInput, 0) ships with implicit-base behavior while looking compliant.
Why this matters
The rule's whole purpose is to stop 0x-prefixed input from being silently read as hex in actions/setup/js runtime scripts. radix 0/undefined reintroduce precisely that hazard, and a developer who wrote parseInt(x, 0) (a common copy/paste mistake) gets no warning.
Acceptance criteria
- The rule reports
parseInt(x, 0) and parseInt(x, undefined) (both global and Number./globalThis./window./global. forms, dot and computed).
- Decide and document the policy for a non-literal radix (
parseInt(x, base)): either accept (current implicit behavior, documented) or warn that the radix could not be statically verified. Recommendation: keep accepting non-literal identifiers to avoid noise, but explicitly reject the literal values 0 and undefined.
- The existing
length >= 2 early return is replaced by a check that inspects the second argument: accept only when it is not a literal 0 and not the identifier/keyword undefined.
- Guard the autofix: the
, 10 insertion must not fire for spread calls (parseInt(...args) reports arguments.length === 1 and would produce the broken parseInt(...args, 10)); skip the suggestion when arguments[0] is a SpreadElement.
- Add tests covering:
parseInt(x, 0) (invalid), parseInt(x, undefined) (invalid), parseInt(x, 16) (valid), parseInt(x, base) (per chosen policy), and parseInt(...args) (no broken fix).
Out of scope
Aliased/destructured parseInt bindings (already tracked in #42017).
Generated by 🤖 ESLint Refiner · 185.1 AIC · ⌖ 12.4 AIC · ⊞ 4.7K · ◷
Summary
require-parseInt-radixshort-circuits on argument count alone:This treats any second argument as a valid radix. But several second-argument values still trigger the exact implicit base detection the rule exists to prevent:
parseInt(str, 0)— radix0is spec-equivalent to no radix: a leading0x/0Xis parsed as hexadecimal.parseInt(str, undefined)— same as omitting the radix.parseInt(str, someVar)wheresomeVaris0/undefined/non-numeric at runtime — not statically a literal10, so the safety claim is unverified.All of these currently pass the rule silently, so
parseInt(userInput, 0)ships with implicit-base behavior while looking compliant.Why this matters
The rule's whole purpose is to stop
0x-prefixed input from being silently read as hex inactions/setup/jsruntime scripts. radix0/undefinedreintroduce precisely that hazard, and a developer who wroteparseInt(x, 0)(a common copy/paste mistake) gets no warning.Acceptance criteria
parseInt(x, 0)andparseInt(x, undefined)(both global andNumber./globalThis./window./global.forms, dot and computed).parseInt(x, base)): either accept (current implicit behavior, documented) or warn that the radix could not be statically verified. Recommendation: keep accepting non-literal identifiers to avoid noise, but explicitly reject the literal values0andundefined.length >= 2early return is replaced by a check that inspects the second argument: accept only when it is not a literal0and not the identifier/keywordundefined., 10insertion must not fire for spread calls (parseInt(...args)reportsarguments.length === 1and would produce the brokenparseInt(...args, 10)); skip the suggestion whenarguments[0]is aSpreadElement.parseInt(x, 0)(invalid),parseInt(x, undefined)(invalid),parseInt(x, 16)(valid),parseInt(x, base)(per chosen policy), andparseInt(...args)(no broken fix).Out of scope
Aliased/destructured
parseIntbindings (already tracked in #42017).