Claude
Skills
Sign in
Back

security-checklist

Included with Lifetime
$97 forever

Comprehensive security checklist covering OWASP Top 10, SQL injection, XSS, CSRF, authentication, authorization, secrets management, input validation, and security headers. Use when scanning for vulnerabilities, reviewing security, implementing authentication/authorization, or handling sensitive data.

Backend & APIs

What this skill does


# Security Checklist

This skill provides comprehensive security guidance to protect your applications from common vulnerabilities and attacks.

## OWASP Top 10 Vulnerabilities

### 1. Broken Access Control

**What it is**: Users can access resources or perform actions they shouldn't be authorized for.

**Examples**:
- Accessing another user's data by changing URL parameter
- Elevating privileges (user → admin)
- Bypassing authentication checks

**Prevention**:
```typescript
// ❌ BAD - No authorization check
app.get('/api/users/:id', async (req, res) => {
  const user = await db.user.findUnique({ where: { id: req.params.id } });
  res.json(user);
});

// ✅ GOOD - Verify ownership or admin
app.get('/api/users/:id', authenticate, async (req, res) => {
  const requestedId = req.params.id;
  const currentUserId = req.user.id;
  const isAdmin = req.user.role === 'admin';

  if (requestedId !== currentUserId && !isAdmin) {
    return res.status(403).json({ error: 'Forbidden' });
  }

  const user = await db.user.findUnique({ where: { id: requestedId } });
  res.json(user);
});
```

**Checklist**:
- [ ] Enforce least privilege (deny by default)
- [ ] Verify user permissions on every request
- [ ] Never trust user IDs from client
- [ ] Log access control failures
- [ ] Use centralized access control logic

### 2. Cryptographic Failures

**What it is**: Exposing sensitive data due to weak or missing encryption.

**Examples**:
- Storing passwords in plain text
- Using weak hashing algorithms (MD5, SHA1)
- Transmitting sensitive data over HTTP

**Prevention**:
```typescript
import bcrypt from 'bcrypt';
import crypto from 'crypto';

// ✅ Password hashing
async function hashPassword(password: string): Promise<string> {
  const saltRounds = 12; // Increase for more security
  return await bcrypt.hash(password, saltRounds);
}

async function verifyPassword(password: string, hash: string): Promise<boolean> {
  return await bcrypt.compare(password, hash);
}

// ✅ Encrypt sensitive data at rest
function encrypt(text: string, key: string): string {
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv('aes-256-gcm', Buffer.from(key), iv);

  let encrypted = cipher.update(text, 'utf8', 'hex');
  encrypted += cipher.final('hex');

  const authTag = cipher.getAuthTag().toString('hex');
  return `${iv.toString('hex')}:${authTag}:${encrypted}`;
}
```

**Checklist**:
- [ ] Use HTTPS everywhere
- [ ] Hash passwords with bcrypt (12+ rounds)
- [ ] Encrypt sensitive data at rest
- [ ] Use strong encryption algorithms (AES-256)
- [ ] Properly manage encryption keys
- [ ] Never commit secrets to version control

### 3. Injection Attacks

**See SQL Injection Prevention section below**

### 4. Insecure Design

**What it is**: Security flaws in the application architecture.

**Examples**:
- Missing rate limiting
- Unrestricted file uploads
- Insecure password reset flows

**Prevention**:
```typescript
// ✅ Rate limiting
import rateLimit from 'express-rate-limit';

const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 5, // 5 attempts
  message: 'Too many login attempts, please try again later',
});

app.post('/api/auth/login', loginLimiter, async (req, res) => {
  // Login logic
});

// ✅ Secure file upload
import multer from 'multer';

const upload = multer({
  limits: {
    fileSize: 5 * 1024 * 1024, // 5MB max
  },
  fileFilter: (req, file, cb) => {
    const allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
    if (!allowedTypes.includes(file.mimetype)) {
      return cb(new Error('Invalid file type'));
    }
    cb(null, true);
  },
});
```

**Checklist**:
- [ ] Implement rate limiting on all endpoints
- [ ] Validate file uploads (type, size, content)
- [ ] Use secure password reset flows (token-based)
- [ ] Implement account lockout after failed attempts
- [ ] Log and monitor security events

### 5. Security Misconfiguration

**What it is**: Insecure default configurations, unnecessary features enabled.

**Prevention**:
```typescript
// ✅ Secure Express configuration
import express from 'express';
import helmet from 'helmet';

const app = express();

// Security headers
app.use(helmet());

// Disable X-Powered-By
app.disable('x-powered-by');

// Environment-specific settings
if (process.env.NODE_ENV === 'production') {
  app.set('trust proxy', 1); // Trust first proxy
}

// CORS configuration
import cors from 'cors';

const corsOptions = {
  origin: process.env.ALLOWED_ORIGINS?.split(',') || [],
  credentials: true,
  optionsSuccessStatus: 200,
};

app.use(cors(corsOptions));
```

**Checklist**:
- [ ] Remove default accounts and passwords
- [ ] Disable directory listing
- [ ] Remove unnecessary features/endpoints
- [ ] Keep all software updated
- [ ] Use security headers (see section below)

### 6. Vulnerable and Outdated Components

**Prevention**:
```bash
# Check for vulnerabilities
npm audit

# Fix vulnerabilities
npm audit fix

# Update dependencies
npm update

# Use automated tools
npm install -g snyk
snyk test
snyk monitor
```

**Checklist**:
- [ ] Regularly update dependencies
- [ ] Monitor security advisories
- [ ] Remove unused dependencies
- [ ] Use dependabot or renovate
- [ ] Pin dependency versions in production

### 7. Identification and Authentication Failures

**See Authentication Best Practices section below**

### 8. Software and Data Integrity Failures

**Prevention**:
```typescript
// ✅ Verify package integrity
// package-lock.json ensures same versions

// ✅ Use Subresource Integrity (SRI) for CDN
<script
  src="https://cdn.example.com/library.js"
  integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
  crossorigin="anonymous"
></script>

// ✅ Validate data from external sources
import { z } from 'zod';

const ExternalDataSchema = z.object({
  id: z.string().uuid(),
  amount: z.number().positive(),
  status: z.enum(['pending', 'completed', 'failed']),
});

function processExternalData(data: unknown) {
  const validated = ExternalDataSchema.parse(data);
  // Now safe to use
}
```

### 9. Security Logging and Monitoring Failures

**Prevention**:
```typescript
import winston from 'winston';

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' }),
  ],
});

// ✅ Log security events
logger.warn('Failed login attempt', {
  email: req.body.email,
  ip: req.ip,
  userAgent: req.get('user-agent'),
  timestamp: new Date().toISOString(),
});

logger.error('SQL injection attempt detected', {
  query: sanitizedQuery,
  ip: req.ip,
  endpoint: req.path,
});
```

**Checklist**:
- [ ] Log authentication events (login, logout, failures)
- [ ] Log authorization failures
- [ ] Log input validation failures
- [ ] Monitor for suspicious patterns
- [ ] Set up alerts for security events

### 10. Server-Side Request Forgery (SSRF)

**Prevention**:
```typescript
import validator from 'validator';

// ❌ BAD - Allows SSRF
app.post('/api/fetch-url', async (req, res) => {
  const url = req.body.url;
  const response = await fetch(url);
  res.json(await response.json());
});

// ✅ GOOD - Validate and whitelist
app.post('/api/fetch-url', async (req, res) => {
  const url = req.body.url;

  // Validate URL format
  if (!validator.isURL(url, { protocols: ['https'] })) {
    return res.status(400).json({ error: 'Invalid URL' });
  }

  // Whitelist allowed domains
  const allowedDomains = ['api.trusted-service.com'];
  const urlObj = new URL(url);

  if (!allowedDomains.includes(urlObj.hostname)) {
    return res.status(403).json({ error: 'Domain not allowed' });
  }

  // Block internal IPs
  const hostname = urlObj.hostname;
  if (
    hostname === 'localhost' ||
    hostname.startsWith('192.168.') ||
    hostname.startsWith('10.') ||
    hostname.startsWith('172.')
  ) {
    return res.status(403).json({ error: 'In

Related in Backend & APIs