Summary
The require-json-parse-try-catch rule (actions/setup/js/eslint-factory/src/rules/require-json-parse-try-catch.ts) only matches a CallExpression whose callee is a direct MemberExpression with object.name === "JSON" and a non-computed property.name === "parse". Any indirect reference to JSON.parse bypasses the rule entirely, so an unguarded parse can ship without a warning.
Missed patterns (false negatives)
- Computed access:
JSON["parse"](raw) — property is a string Literal, not an Identifier, so the property.type !== "Identifier" guard returns early.
- Aliased binding:
const p = JSON.parse; p(raw).
- Destructured binding:
const { parse } = JSON; parse(raw).
A grep of actions/setup/js/*.cjs shows 0 current indirect usages, so this is preventive hardening rather than a live regression — but the gap means the rule silently under-reports the moment such code is introduced.
Acceptance criteria
Notes
Keep the matcher precise: only treat a "parse" member of an object resolving to the global JSON as in scope; do not flag unrelated .parse members (e.g. path.parse, Number.parse*).
Generated by 🤖 ESLint Refiner · 142.2 AIC · ⌖ 11.9 AIC · ⊞ 4.7K · ◷
Summary
The
require-json-parse-try-catchrule (actions/setup/js/eslint-factory/src/rules/require-json-parse-try-catch.ts) only matches aCallExpressionwhose callee is a directMemberExpressionwithobject.name === "JSON"and a non-computedproperty.name === "parse". Any indirect reference toJSON.parsebypasses the rule entirely, so an unguarded parse can ship without a warning.Missed patterns (false negatives)
JSON["parse"](raw)—propertyis a stringLiteral, not anIdentifier, so theproperty.type !== "Identifier"guard returns early.const p = JSON.parse; p(raw).const { parse } = JSON; parse(raw).A grep of
actions/setup/js/*.cjsshows 0 current indirect usages, so this is preventive hardening rather than a live regression — but the gap means the rule silently under-reports the moment such code is introduced.Acceptance criteria
JSON["parse"](x)(computed member with a"parse"string-literal key) when not inside a protecting try block.JSON.parsealiases, OR explicitly document them as out of scope with a code comment and a follow-up note.JSON.parsecall sites inactions/setup/js.Notes
Keep the matcher precise: only treat a
"parse"member of an object resolving to the globalJSONas in scope; do not flag unrelated.parsemembers (e.g.path.parse,Number.parse*).