Changelog
Release history and version updates for eslint-plugin-lambda-security
Live from GitHub
This changelog is fetched directly from CHANGELOG.md on GitHub and cached for 2 hours.
[1.2.3] - 2026-02-08
1.3.1
Patch Changes
- #364
86baa02Thanks @ofri-peretz! - Add the ecosystem and oxlint marks to the README logo row. Each plugin now leads with Interlace -> its ecosystem (node, nestjs, express, react, mongodb, postgresql, mysql, sqlite, prisma, drizzle, knex, typeorm, sequelize, lambda, vercel, jwt) -> oxlint -> ESLint; the generic quality plugins carry the row without an ecosystem mark. README-only change - no rule behaviour is affected. The patch bump is what carries the new README onto npm, which only refreshes a package README on publish.
1.3.0
Minor Changes
-
#325
baefb93Thanks @ofri-peretz! -no-permissive-cors-response: remove the deadallowedOriginsoption.The option was declared in the rule's
Optionsinterface, its JSONschema(described as "Patterns for allowed origins"), and itsdefaultOptions— butcreate()only ever readallowInTests. Configuring['error', { allowedOrigins: ['https://foo.com'] }]passed ESLint's schema validation and then did nothing, with no error to tip the user off.Removed rather than implemented. The rule reports on exactly one value — the literal
'*'— so an allowlist of concrete origins can never match anything it flags. Making the option meaningful would mean widening the rule to flag any hardcoded origin, which would newly report code the rule's own autofix produces ("https://your-domain.com"). That is a different rule, not a bug fix.Migration: if you had
allowedOriginsin your config, delete it — it never had an effect. Because the schema usesadditionalProperties: false, leaving it in place now surfaces an ESLint config validation error instead of being silently ignored.Locked by a schema assertion in both
no-permissive-cors-responseand its siblingno-permissive-cors-middy(already clean) that fails if either rule declares an optioncreate()does not read.
Patch Changes
-
#358
1b8c0dfThanks @ofri-peretz! - Fix SDK peer declarations that npm silently ignoredSeven plugins listed their target SDKs under
peerDependenciesMetawith{"optional": true}but never declared them inpeerDependencies. npm drops anypeerDependenciesMetaentry that has no matchingpeerDependencieskey, so the metadata was inert — these packages effectively declared no SDK peer at all. Nothing warned: the failure mode of a dependency you never declared is silence.Each SDK now appears in both maps, matching the shape
eslint-plugin-pgandeslint-plugin-mongodb-securityalready use — a supported major range inpeerDependencies,optional: trueinpeerDependenciesMeta:Plugin SDK Range express-securityexpress^4.0.0 || ^5.0.0helmet^6.0.0 || ^7.0.0 || ^8.0.0cors^2.0.0csurf^1.0.0express-rate-limit^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0jwtjsonwebtoken^8.0.0 || ^9.0.0@nestjs/jwt^9.0.0 || ^10.0.0 || ^11.0.0express-jwt^7.0.0 || ^8.0.0jose^4.0.0 || ^5.0.0 || ^6.0.0jwks-rsa^3.0.0 || ^4.0.0jwt-decode^3.0.0 || ^4.0.0lambda-security@aws-sdk/client-lambda^3.0.0@middy/core^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0@middy/http-cors^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0@middy/http-security-headers^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0@middy/validator^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0maintainabilitytypescript>=4.8.4nestjs-security@nestjs/common^9.0.0 || ^10.0.0 || ^11.0.0@nestjs/throttler^4.0.0 || ^5.0.0 || ^6.0.0class-validator^0.14.0 || ^0.15.0class-transformer^0.5.0react-featurestypescript>=4.8.4vercel-ai-securityai^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0Ranges were taken from each SDK's real release history, bounded below by the oldest major whose call shape the rules still match and above by the current major.
cors,csurf,class-transformerand@aws-sdk/client-lambdahave only ever shipped one usable major. Theairange spans v4 becauserequire-max-stepsdeliberately accepts both the v4maxStepsoption and the v5+stopWhenform. The twotypescriptentries reuse the>=4.8.4bound@interlace/eslint-devkitalready declares, since these are the same type-aware-graceful rules behind the same optional TS program.Every range admits the version this repo's
__compatibility__specs are actually tested against, so the declaration cannot drift from what CI proves.Nothing to migrate. Every entry stays optional, so no install adds a package or emits a warning when the SDK is absent. What changes is that a consumer on an unsupported major now gets a peer warning instead of nothing — which was the point of the metadata in the first place.
-
Updated dependencies [
e8e9ee6]:- @interlace/eslint-devkit@1.7.0
1.2.11
Patch Changes
-
#338
dc25c81Thanks @ofri-peretz! - Re-publish every package so npm carries the optimised artifactNo source changed. This is a no-op patch whose entire purpose is to ship the artifact the current build already produces.
Manifests.
scriptsanddevDependenciesare now stripped from every publishedpackage.json. Neither can do anything in a consumer’s node_modules — npm never runs one and never installs the other — but they shipped in all 27 manifests, cluttered the npm page, and were read by SCA tools scanning installed manifests. No package declares a lifecycle hook, so nothing observable changes. Every published package is bumped so this applies uniformly rather than to a subset.Tarballs. 20 packages were last published before the build pipeline changed and still ship
AGENTS.md,CHANGELOG.md, JSDoc in the emitted.js, and the full generated.d.tstree:package published rebuilt saving eslint-plugin-react-features547 kB 320 kB −227 kB eslint-plugin-secure-coding653 kB 477 kB −176 kB eslint-plugin-conventions241 kB 116 kB −125 kB eslint-plugin-browser-security380 kB 291 kB −89 kB eslint-plugin-maintainability178 kB 116 kB −62 kB eslint-plugin-react-a11y232 kB 173 kB −59 kB eslint-plugin-reliability148 kB 90 kB −58 kB eslint-plugin-vercel-ai-security187 kB 130 kB −57 kB eslint-plugin-operability90 kB 43 kB −47 kB eslint-plugin-jwt140 kB 95 kB −45 kB eslint-plugin-modularity98 kB 58 kB −40 kB eslint-plugin-nestjs-security122 kB 86 kB −36 kB eslint-plugin-sqlite-security54 kB 20 kB −34 kB eslint-plugin-sequelize-security54 kB 21 kB −34 kB eslint-plugin-prisma-security52 kB 19 kB −33 kB eslint-plugin-mysql-security52 kB 19 kB −33 kB eslint-plugin-typeorm-security52 kB 19 kB −33 kB eslint-plugin-drizzle-security52 kB 19 kB −33 kB eslint-plugin-knex-security51 kB 19 kB −32 kB eslint-plugin-modernization45 kB 38 kB −7 kB Those 20 go from 3428 kB to 2169 kB — −36.7%. The remaining 7 were released after the pipeline change and only gain the manifest strip.
A new check in
scripts/check-published-artifacts.tsfails the build ifscriptsordevDependenciesever reappear in a published manifest, so the strip cannot silently regress.The dependency ranges did not need updating: every plugin pins
@interlace/eslint-devkitwith a caret that 1.6.0 satisfies, verified by a clean install of an unchanged plugin resolving devkit 1.6.0 with zero dependencies and notypescriptin the tree. -
Updated dependencies [
dc25c81]:- @interlace/eslint-devkit@1.6.1
1.2.10
Patch Changes
-
#311
9e93ae2Thanks @ofri-peretz! - Close two detection gaps found while linting a real serverless example.no-unvalidated-event-body— see past value-preserving wrappers. The safe-pattern checks only looked atevent.body's direct parent, soschema.safeParse(JSON.parse(event.body ?? '{}'))— the standard way to give an optional API Gateway body a default — was a CVSS 8.0 finding: the??sat between the property access and the validating call and defeated every check. The rule now walks past??/||,asassertions and!non-null assertions before deciding, which also fixesif (event.httpMethod === 'POST' && event.body)being reported as unvalidated.no-permissive-cors-response— read implicit-return arrow bodies. The rule only inspected explicitreturn { statusCode, headers, body }statements and*response*-named variables, so the idiomatic response helperconst jsonResponse = (statusCode, data) => ({ statusCode, headers: { 'Access-Control-Allow-Origin': '*' }, body: JSON.stringify(data) })was invisible — the exact shape most handlers funnel every response through. Concise arrow bodies returning a Lambda-shaped object are now checked, with the samestatusCode/bodygate so ordinary config objects stay unflagged. -
Updated dependencies [
a5fad9f,0231140,4cc62d6]:- @interlace/eslint-devkit@1.6.0
1.2.9
Patch Changes
-
#294
659f6dcThanks @ofri-peretz! - Rewritedescriptionandkeywordson every published package for npm search discovery. npm ranks on name, description, and keywords, and the registry only picks up these fields at publish — so this is metadata-only and takes effect for each package on its next release.Descriptions now lead with the search phrase. Every one starts
ESLint plugin for <the thing you'd search>instead of a brand-first or category-first framing, and names the concrete vulnerabilities the plugin actually detects. Three were corrected while doing so:eslint-plugin-import-nextclaimed "100x faster no-cycle detection". No 100x measurement exists:CLAIMS.mdrecords 3.1x end-to-end (8x in pure rule execution) on a 5,483-file React codebase, and the highest number in any benchmark result is 54.9x on the synthetic corpus. The description now states the real-codebase figure.eslint-plugin-secure-codingclaimed SQL injection, XSS and CSRF coverage — none of which are its rules. It now names what it does detect: LDAP, XPath, XXE, GraphQL and template injection, unsafe deserialization, ReDoS, missing authentication, and PII in logs.eslint-plugin-secure-coding("89 rules") andeslint-plugin-react-a11y("37 rules") hard-coded rule counts that had drifted from reality. Counts are generated intointerlace-numbers.json; hand-typed copies are removed rather than corrected.
Keywords now match the vocabulary of the plugins that rank.
eslint-plugin-security,eslint-plugin-jsx-a11y,eslint-plugin-nandeslint-plugin-importall carry theeslint/eslintplugin/eslint-plugintrio — six of our packages were missingeslintplugin, and every one now carries all three plusstatic-analysis,lintingandcode-quality. Security plugins addsast,appsecandvulnerability;node-securityandsecure-codingalso carrynodesecurity, the exact keywordeslint-plugin-securityranks on. Each plugin gained the CWE identifiers and attack names for what it detects (cwe-78command injection,cwe-22path traversal,cwe-89SQL injection,cwe-79XSS,cwe-347JWT algorithm confusion,cwe-352CSRF,cwe-943NoSQL injection), andnode-securitygained the crypto vocabulary it had been missing entirely despite absorbing the crypto rule set (crypto,cryptography,weak-hash,md5,sha1,timing-attack).No rule behavior, exports, or configuration changes.
-
Updated dependencies [
e1cdf83,659f6dc]:- @interlace/eslint-devkit@1.4.3
1.2.8
Patch Changes
-
#269
7028fe2Thanks @ofri-peretz! - docs: dual-logo README header (Interlace mark + ESLint mark side by side) and closing Interlace footer — refreshes the README rendered on npmjs.com. No runtime changes. -
Updated dependencies [
7028fe2]:- @interlace/eslint-devkit@1.4.2
1.2.7
Patch Changes
- #252
d67e395Thanks @ofri-peretz! - Fix Codecov badge showing "unknown" — switch from flag to component URL format
1.2.6
Patch Changes
- #225
34ff5a8Thanks @ofri-peretz! - CI-only: pin all coverage thresholds at 100% (integration target, merges last).
1.2.5
Patch Changes
-
#220
ad8416dThanks @ofri-peretz! - Fix runtime crashes when linting realistic AWS Lambda handlers under ESLint 9.The published
1.2.3tarball was a stale build: its rules still threw on the generated lambda-ai-corpus handlers, even though source had already been fixed. This republishes the corrected build and locks it with a regression test.no-error-swallowingno longer throwsRangeError: Maximum call stack size exceeded. The old build walked the catch-block AST by hand and recursed through the cyclicnode.parentreference; source now usessourceCode.getText()+ a regex.require-timeout-handling,no-missing-authorization-check, andno-unbounded-batch-processingno longer throwError: Unknown class name: exit. They used a grouped:exitselector ('A:exit, B:exit, C:exit'); ESLint only strips the trailing:exit, so esquery received a bare:exit. Source now uses one listener key per node type.plugin.meta.versionis now read frompackage.jsoninstead of a hardcoded string, so a build can no longer mislabel its own version (1.2.3 embedded1.1.0).
-
#213
391dbe6Thanks @ofri-peretz! - Align every security rule'smeta.docs.cvssto the CVSS its finding actually emits. The emitted machine-readable message sources itsCVSS:xfromCWE_MAPPINGviaformatLLMMessage→enrichFromCWE, but the staticmeta.docs.cvssdocumentation field had drifted on 45 rules across these 7 plugins — e.g.no-hardcoded-credentialsdocumented9.5while emittingCVSS:9.8(the value the published article and SARIF/LLM consumers already read).This corrects the documentation metadata only — no emitted finding changes. Locked by
security-cvss-docs-consistency.lock.test.ts(cross-plugin: every security rule'smeta.docs.cvssmust equal the CVSS it emits), theno-hardcoded-credentialsrule lock (real ESLintLinteremission), and a devkitenrichFromCWEcontract test pinningCWE-798 → 9.8.Follow-up (not in scope): 50 security rules document a CVSS that never appears in any emitted message (their messages carry no CWE), and several rules emit the generic CWE score where a rule-specific score may be warranted — both change emitted output and are separate decisions.
1.2.4
Patch Changes
-
#144
8843ce7Thanks @ofri-peretz! - fix: ILB-Wild FP reduction + doc examples + doc-test-alignment scanner fixesno-unlimited-resource-allocation— FP reduction (430 Edge FPs)- Skip loop-allocation reporting when the first argument is a numeric literal (e.g.
Buffer.alloc(1024)inside a loop is statically bounded, not a risk) - Skip
Array.isArray,Array.from,Array.ofcalls in thealloc/Arraypattern check (these don't allocate unbounded memory)
no-hardcoded-credentials— FP reduction (~280 Edge FPs)- Extended test-file skip to cover
.fixture.,.mock.,__mocks__/,/tests/,/fixtures/,/mocks/paths - Skip string literals that are fallback values in
process.env.X || 'fallback'expressions — the secret lives in the environment, the string is only a dev-mode default
Doc examples — 4 rules now have ❌ Incorrect examples
lambda-security/no-missing-authorization-checklambda-security/no-overly-permissive-iam-policynode-security/prefer-native-crypto(renamed non-standard### ❌ Third-Party (Flagged)to### ❌ Incorrect)vercel-ai-security/require-tool-confirmation(replaced placeholder with a real tested example)
ilb-doc-test-alignmentscanner fixes- Accept both
## ❌and### ❌headings (docs use H3 under an H2## Examplessection; was only finding H2) - Slice from end-of-line rather than end-of-regex-match (prevents
## ❌ Incorrect Codefrom leaving a partial heading in the parsed section)
Result:
ilb:doc-test-alignment→ 206 ok, 0 doc has no ❌ examples (was 165 missing). - Skip loop-allocation reporting when the first argument is a numeric literal (e.g.
-
#194
55d5c0aThanks @ofri-peretz! - Fix a hard crash (Error: Unknown class name: exit) that aborted the entire ESLint run on ESLint 9 whenever therecommendedorstrictconfig was enabled.Three rules —
require-timeout-handling,no-missing-authorization-check, andno-unbounded-batch-processing— registered their function-exit listener as a single comma-joined selector key:'ArrowFunctionExpression:exit, FunctionExpression:exit, FunctionDeclaration:exit'ESLint only strips a trailing
:exitbefore handing a selector to esquery, so the earlier:exittokens survived into the parser and threwUnknown class name: exitfor every linted file. Each listener is now registered as one key per node type, which is the only esquery-safe form.A config-level regression test (
src/index.test.ts) now boots the real ESLint engine against both shipped configs, so any future comma-joined:exit— or any other unparseable selector in any rule — fails in CI instead of in a consumer's editor.@interlace/eslint-configre-exports therecommendedconfig and is republished against the fixed plugin. -
#143
213cde1Thanks @ofri-peretz! - fix(no-missing-null-checks): eliminate 53 false positives via three new narrowing patternsRules that were recognized as null guards are now correctly identified as safe:
- Truthy if guard —
if (obj) { obj.prop }— direct truthy check proves non-null. Also covers chains:if (response)protectsresponse.data.items. - Short-circuit AND —
obj && obj.prop— right side of&&only runs when left is truthy. - Ternary consequent —
obj ? obj.prop : fallback— truthy test guards the consequent.
Also: bumped
beforeAlltimeout to 30 seconds in 7 compatibility test files (__compatibility__/*.spec.ts). Native-addon packages routinely exceed the previous 10-second default on a cold ESM load. - Truthy if guard —
-
Updated dependencies [
736a5fe]:- @interlace/eslint-devkit@1.4.1
Bug Fixes
- align codecov component IDs with full package names (2831b968)
Documentation
- fix changelog header format across all packages (c3a15082)
❤️ Thank You
- Ofri Peretz
[1.2.2] - 2026-02-06
Bug Fixes
- align codecov component names and update docs components (0a59a86c)
❤️ Thank You
- Ofri Peretz
[1.2.1] - 2026-02-02
This was a version bump only for eslint-plugin-lambda-security to align it with other projects, there were no code changes.
Changelog
All notable changes to eslint-plugin-lambda-security will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[1.0.0] - 2025-12-29
Added
Credential & Secrets Protection Rules (3)
no-hardcoded-credentials-sdk- Detect hardcoded AWS credentials in SDK v3 clients (CWE-798)no-secrets-in-env- Detect secrets hardcoded in environment variables (CWE-798)no-env-logging- Detect logging entire process.env object (CWE-532)
CORS Security Rules (2)
no-permissive-cors-response- Detect wildcard CORS in Lambda response headers (CWE-942)no-permissive-cors-middy- Detect permissive CORS in @middy/http-cors middleware (CWE-942)
Presets (2)
recommended- Balanced security defaultsstrict- All 5 rules as errors
Features
- LLM-optimized error messages with CWE references
- OWASP Serverless Top 10 alignment (SAS-2, SAS-3, SAS-4)
- AWS SDK v3 client detection (S3, DynamoDB, Lambda, STS, etc.)
- Middy middleware detection (@middy/http-cors)
- Real AWS access key pattern matching (AKIA*, ASIA*)
- TypeScript support with exported option types
- Comprehensive test coverage (78 tests, 97.40% line coverage)
- Auto-fix for CORS violations
Security
- Covers 3 CWEs: 532, 798, 942
- Maps to OWASP Serverless Top 10: SAS-2, SAS-3, SAS-4
View on GitHub →
Building secure JavaScript with Interlace? Star the repo to get new rules and CWE coverage as we ship them — or follow the AI-code-security benchmarks behind them.