fix(eslint-plugin): close 3 false-negatives + add additionalPatterns option (#1758)#1762
Merged
Merged
Conversation
…option (#1758) Three bug-class false-negatives in `no-credential-read-from-args` now fire: - Destructure-then-read: `extractContext(args) { const { access_token } = args; ... }` (new `VariableDeclarator` visitor; recurses through nested `ObjectPattern`s and reports at the source key, not the alias). - `AssignmentPattern` default-value silently disabled scanning: `extractContext(args = {}) { args.access_token }` now unwraps `AssignmentPattern.left` in `firstParamIdentifierName`. `extractContext({ access_token } = {})` likewise. - Nested destructure in first param: `extractContext({ context: { access_token } })` now recurses and reports the full dotted path (`args.context.access_token`). Nested renames fire on the source key. New `additionalPatterns` rule option lets adopters who extend the runtime matcher via `credentialPolicy.patterns.extend(...)` mirror the same strings at lint time. Compiled with the `i` flag and appended to `DEFAULT_CREDENTIAL_PATTERNS`. Fully-replaceable `credentialPolicy.matcher` functions stay a documented gap. False-positive fix: free-standing `function extractContext(args) { ... }` no longer fires — only `Property` and `MethodDefinition` method bindings are matched. Class methods still fire (regression-covered). README adds a `Known gaps` section documenting aliasing / spread / helper-indirection / computed-key / cross-function bypasses that pass the linter by design. Test count: 14 → 30. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
2 tasks
bokelley
added a commit
that referenced
this pull request
May 15, 2026
…1766) (#1767) * fix(ci): run packages/eslint-plugin/ tests as part of root npm test (#1766) Chain `npm test --workspaces --if-present` onto the root test script so CI's Test & Build job (which runs `npm test`) exercises the ESLint plugin's rule tests. Plugin tests landed in PR #1762 but weren't running in CI, so plugin regressions could land on main silently. `--workspaces --if-present` is forward-compatible: any future workspace that adds a `test` script is automatically picked up. `packages/client-shim` has no `test` script and is correctly skipped. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(ci): avoid root test recursion by targeting plugin workspace explicitly Root package.json declares workspaces as [".", "packages/*"], so `npm test --workspaces` re-invokes the root test script, which recurses indefinitely until CI cancels. Switch to an explicit `--workspace=packages/eslint-plugin` invocation so the plugin tests run exactly once. Future workspaces with test scripts get appended explicitly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Closes #1758.
Summary
Closes the three false-negative gaps in
no-credential-read-from-args(shipped in #1752, on main but not yet released — the existing minor changeset is still pending) and adds anadditionalPatternsrule option for adopters extending the runtime matcher.Bug-class fixes
extractContext(args) { const { access_token } = args; ... }previously passed. NewVariableDeclaratorvisitor handles this, recursing through nestedObjectPatterns and reporting at the source key (not the alias). SharescollectObjectPatternKeyswith the first-param destructure scanner so both forms produce identical paths.AssignmentPatterndefault-value silently disabled scanning —extractContext(args = {})previously madefirstParamIdentifierNamereturnnull, which disabled theMemberExpressionscanner. Now unwrapsAssignmentPattern.leftto recover the identifier name.extractContext({ access_token } = {})likewise —destructuredKeysunwraps theAssignmentPatternwrapper before pattern-walking.extractContext({ context: { access_token } })previously only inspected the top-level pattern.collectObjectPatternKeysnow recurses into nestedObjectPatterns and tracks the full path so the error message readsargs.context.access_token. Nested renames ({ context: { access_token: tok } }) fire on the source key.RestElementskipped (documented gap).False-positive fix
Free-standing
function extractContext(args) { return args.access_token; }no longer fires. Dropped theFunctionDeclarationbranch frommethodNameForFunction— onlyProperty(object literals) andMethodDefinition(class bodies) are matched. Class methods still fire (three regression tests cover this).Rule option
New
additionalPatterns: string[]option. Each entry compiled asnew RegExp(p, 'i')and appended toDEFAULT_CREDENTIAL_PATTERNS. Adopters mirror theircredentialPolicy.patterns.extend(...)runtime config for lint parity. Fully-replaceablecredentialPolicy.matcherfunctions documented as a known gap (no regex analogue).README
Adds
Known gapssection listing aliasing / spread / helper-indirection / computed-key / cross-function bypasses that pass the linter by design — runtimecredentialPolicy: 'authInfo-only'is the security boundary. Adds anadditionalPatternsoption example with matching runtime config.Test count
14 → 30. New invalid cases: destructure-then-read (incl. rename, with-default, with-leaf-default), default-value param, destructure-with-default first param, nested destructure (plain + rename),
additionalPatterns(member + destructure), class-method regression for each of the three fixes. New valid cases: free-standingfunction extractContext, spread aliasing, plain aliasing, destructure-then-read of a non-credential key.Changeset
patchon@adcp/eslint-plugin.Test plan
cd packages/eslint-plugin && npm test— 30/30 passcd packages/eslint-plugin && npm run build— cleannpm run format:check— clean🤖 Generated with Claude Code