13 Lambda security rules. OWASP Serverless Top 10. AWS best practices.
Who Is This For?
This plugin is for Node.js teams building serverless applications on AWS:
| Framework | Description |
|---|---|
| AWS Lambda | Native function handlers |
| Serverless Framework | Most popular serverless deployment tool |
| AWS SAM CLI | AWS-native IaC for Lambda |
| Middy.js | Middleware engine for Lambda (we have specific rules!) |
If you deploy functions to Lambda β whether via CDK, SAM, Serverless Framework, or raw CloudFormation β this plugin catches security issues before they reach production.
Quick Install
npm install --save-dev eslint-plugin-lambda-security
Flat Config
// eslint.config.js
import lambdaSecurity from 'eslint-plugin-lambda-security';
export default [lambdaSecurity.configs.recommended];
Rule Overview
Based on the OWASP Serverless Top 10:
| Rule | OWASP | What it catches |
|---|---|---|
no-unvalidated-event-body |
S1, S10 | Injection via event |
no-missing-authorization-check |
S2 | No auth in handlers |
no-exposed-error-details |
S3 | Stack traces in errors |
no-unbounded-batch-processing |
S4 | Large batch DoS |
no-overly-permissive-iam-policy |
S5 |
* in IAM |
no-permissive-cors-response |
S6 | CORS misconfiguration |
no-error-swallowing |
S7 | Empty catch blocks |
no-secrets-in-env |
S8 | Secrets in env vars |
no-user-controlled-requests |
S9 | SSRF |
no-env-logging |
S3 | Env logged |
no-hardcoded-credentials-sdk |
S8 | AWS creds in code |
no-permissive-cors-middy |
S6 | Middy CORS |
require-timeout-handling |
S4 | No timeout fallback |
Run ESLint
npx eslint .
You'll see output like:
src/handlers/api.ts
12:5 error π OWASP-S3 | Error details exposed to client
Fix: Return generic error message, log details internally
src/handlers/batch.ts
28:3 error π OWASP-S4 | Unbounded batch processing detected
Fix: Add batch size limit: records.slice(0, 100)
src/config/cors.ts
8:1 error π OWASP-S6 | Permissive CORS origin '*'
Fix: Specify allowed origins: ['https://app.example.com']
Quick Wins
Error Handling
// β Dangerous: Exposes stack trace
export const handler = async (event) => {
try {
return await processEvent(event);
} catch (error) {
return { statusCode: 500, body: JSON.stringify({ error: error.stack }) };
}
};
// β
Safe: Generic error, internal logging
export const handler = async (event) => {
try {
return await processEvent(event);
} catch (error) {
console.error('Handler error:', error); // Logged to CloudWatch
return {
statusCode: 500,
body: JSON.stringify({ error: 'Internal error' }),
};
}
};
CORS Configuration
// β Dangerous: Wildcard origin
return {
statusCode: 200,
headers: { 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify(data),
};
// β
Safe: Explicit origin
return {
statusCode: 200,
headers: { 'Access-Control-Allow-Origin': 'https://app.example.com' },
body: JSON.stringify(data),
};
Custom Configuration
Add specific rules or customize options:
// eslint.config.js
import lambdaSecurity from 'eslint-plugin-lambda-security';
export default [
lambdaSecurity.configs.recommended,
{
rules: {
// Override severity
'lambda-security/no-error-swallowing': 'warn',
// Configure with options
'lambda-security/no-unbounded-batch-processing': [
'error',
{
maxBatchSize: 50,
},
],
// Disable a rule
'lambda-security/no-env-logging': 'off',
},
},
];
Strongly-Typed Options (TypeScript)
The plugin exports types for IDE autocompletion:
// eslint.config.ts
import lambdaSecurity, {
type RuleOptions,
} from 'eslint-plugin-lambda-security';
const batchOptions: RuleOptions['no-unbounded-batch-processing'] = {
maxBatchSize: 100,
allowedSources: ['SQS', 'Kinesis'],
};
export default [
lambdaSecurity.configs.recommended,
{
rules: {
'lambda-security/no-unbounded-batch-processing': ['error', batchOptions],
},
},
];
Quick Reference
# Install
npm install --save-dev eslint-plugin-lambda-security
# Config (eslint.config.js)
import lambdaSecurity from 'eslint-plugin-lambda-security';
export default [lambdaSecurity.configs.recommended];
# Run
npx eslint .
π¦ npm: eslint-plugin-lambda-security
π OWASP Serverless Mapping
π Building on Lambda? Run the linter!
Top comments (0)