security

Web Application Security

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "security" with this command: npx skills add vapvarun/claude-backup/vapvarun-claude-backup-security

Web Application Security

Security best practices and vulnerability prevention.

OWASP Top 10

  1. Injection (SQL, NoSQL, Command)

// BAD: SQL Injection const query = SELECT * FROM users WHERE email = '${email}'; db.query(query);

// GOOD: Parameterized queries const query = 'SELECT * FROM users WHERE email = ?'; db.query(query, [email]);

// GOOD: Using ORM const user = await User.findOne({ where: { email } });

// BAD: Command injection const output = execSync(ls ${userInput});

// GOOD: Avoid shell, use array const output = execFileSync('ls', [sanitizedPath]);

// BAD: NoSQL injection db.users.find({ username: req.body.username, password: req.body.password });

// GOOD: Type validation const username = String(req.body.username); const password = String(req.body.password); db.users.find({ username, password });

  1. Broken Authentication

// Password hashing import bcrypt from 'bcrypt';

const SALT_ROUNDS = 12;

async function hashPassword(password) { return bcrypt.hash(password, SALT_ROUNDS); }

async function verifyPassword(password, hash) { return bcrypt.compare(password, hash); }

// Session management import session from 'express-session'; import RedisStore from 'connect-redis';

app.use(session({ store: new RedisStore({ client: redisClient }), secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, cookie: { secure: true, // HTTPS only httpOnly: true, // No JavaScript access sameSite: 'strict', // CSRF protection maxAge: 3600000, // 1 hour }, }));

// 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, try again later', standardHeaders: true, legacyHeaders: false, });

app.post('/login', loginLimiter, loginHandler);

  1. Sensitive Data Exposure

// Never log sensitive data // BAD console.log('User login:', { email, password });

// GOOD console.log('User login:', { email, password: '[REDACTED]' });

// Encrypt sensitive data at rest import crypto from 'crypto';

const ENCRYPTION_KEY = Buffer.from(process.env.ENCRYPTION_KEY, 'hex'); const IV_LENGTH = 16;

function encrypt(text) { const iv = crypto.randomBytes(IV_LENGTH); const cipher = crypto.createCipheriv('aes-256-gcm', ENCRYPTION_KEY, iv);

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

const authTag = cipher.getAuthTag();

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

}

function decrypt(encryptedData) { const [ivHex, authTagHex, encrypted] = encryptedData.split(':'); const iv = Buffer.from(ivHex, 'hex'); const authTag = Buffer.from(authTagHex, 'hex');

const decipher = crypto.createDecipheriv('aes-256-gcm', ENCRYPTION_KEY, iv);
decipher.setAuthTag(authTag);

let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');

return decrypted;

}

  1. XML External Entities (XXE)

// BAD: Default parser may be vulnerable const parser = new DOMParser(); const doc = parser.parseFromString(xmlString, 'text/xml');

// GOOD: Disable external entities import { XMLParser } from 'fast-xml-parser';

const parser = new XMLParser({ allowBooleanAttributes: true, ignoreAttributes: false, // Disable external entities and DTD processing });

const result = parser.parse(xmlString);

  1. Broken Access Control

// IDOR Prevention // BAD: Direct object reference app.get('/api/orders/:id', async (req, res) => { const order = await Order.findById(req.params.id); res.json(order); // Any user can access any order! });

// GOOD: Verify ownership app.get('/api/orders/:id', async (req, res) => { const order = await Order.findOne({ _id: req.params.id, userId: req.user.id, // Only owner's orders });

if (!order) {
    return res.status(404).json({ error: 'Not found' });
}

res.json(order);

});

// Role-based access control function requireRole(...roles) { return (req, res, next) => { if (!req.user || !roles.includes(req.user.role)) { return res.status(403).json({ error: 'Forbidden' }); } next(); }; }

app.delete('/api/users/:id', requireRole('admin'), deleteUser);

  1. Security Misconfiguration

// Security headers import helmet from 'helmet';

app.use(helmet({ contentSecurityPolicy: { directives: { defaultSrc: ["'self'"], scriptSrc: ["'self'", "'unsafe-inline'"], // Avoid if possible styleSrc: ["'self'", "'unsafe-inline'"], imgSrc: ["'self'", 'data:', 'https:'], connectSrc: ["'self'", 'https://api.example.com'], frameSrc: ["'none'"], objectSrc: ["'none'"], }, }, crossOriginEmbedderPolicy: true, crossOriginOpenerPolicy: true, crossOriginResourcePolicy: { policy: 'same-site' }, hsts: { maxAge: 31536000, includeSubDomains: true, preload: true, }, }));

// Disable server info app.disable('x-powered-by');

// Error handling - don't leak stack traces app.use((err, req, res, next) => { console.error(err.stack); // Log full error

res.status(500).json({
    error: process.env.NODE_ENV === 'production'
        ? 'Internal server error'
        : err.message,
});

});

  1. Cross-Site Scripting (XSS)

// Input sanitization import DOMPurify from 'dompurify'; import { JSDOM } from 'jsdom';

const window = new JSDOM('').window; const purify = DOMPurify(window);

// Sanitize HTML input const cleanHtml = purify.sanitize(userInput);

// Output encoding import { encode } from 'html-entities';

const safeOutput = encode(userInput);

// React automatically escapes function Comment({ text }) { return <p>{text}</p>; // Safe - React escapes }

// BAD: dangerouslySetInnerHTML <div dangerouslySetInnerHTML={{ __html: userInput }} /> // XSS risk!

// GOOD: sanitize first <div dangerouslySetInnerHTML={{ __html: purify.sanitize(userInput) }} />

  1. Insecure Deserialization

// BAD: Deserializing untrusted data const data = JSON.parse(userInput); eval(data.callback); // Remote code execution!

// GOOD: Validate schema import Ajv from 'ajv';

const ajv = new Ajv(); const schema = { type: 'object', properties: { name: { type: 'string', maxLength: 100 }, age: { type: 'integer', minimum: 0, maximum: 150 }, }, required: ['name'], additionalProperties: false, };

const validate = ajv.compile(schema); const data = JSON.parse(userInput);

if (!validate(data)) { throw new Error('Invalid data'); }

  1. Using Components with Known Vulnerabilities

Check for vulnerabilities

npm audit npm audit fix

Use Snyk for deeper analysis

npx snyk test

Keep dependencies updated

npx npm-check-updates -u

Lock file for reproducible builds

npm ci # Use in CI/CD

  1. Insufficient Logging & Monitoring

// Security event logging import winston from 'winston';

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

// Log security events function logSecurityEvent(event, details) { securityLogger.info({ timestamp: new Date().toISOString(), event, ...details, ip: details.req?.ip, userAgent: details.req?.get('user-agent'), }); }

// Usage app.post('/login', async (req, res) => { try { const user = await authenticate(req.body);

    logSecurityEvent('LOGIN_SUCCESS', {
        req,
        userId: user.id,
    });

    // ...
} catch (error) {
    logSecurityEvent('LOGIN_FAILURE', {
        req,
        email: req.body.email,
        reason: error.message,
    });

    // ...
}

});

Authentication

JWT Best Practices

import jwt from 'jsonwebtoken';

const ACCESS_TOKEN_SECRET = process.env.ACCESS_TOKEN_SECRET; const REFRESH_TOKEN_SECRET = process.env.REFRESH_TOKEN_SECRET;

// Short-lived access token function generateAccessToken(user) { return jwt.sign( { userId: user.id, role: user.role }, ACCESS_TOKEN_SECRET, { expiresIn: '15m', algorithm: 'HS256' } ); }

// Long-lived refresh token function generateRefreshToken(user) { return jwt.sign( { userId: user.id, tokenVersion: user.tokenVersion }, REFRESH_TOKEN_SECRET, { expiresIn: '7d', algorithm: 'HS256' } ); }

// Verify middleware function authenticate(req, res, next) { const authHeader = req.headers.authorization;

if (!authHeader?.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Missing token' });
}

const token = authHeader.split(' ')[1];

try {
    const payload = jwt.verify(token, ACCESS_TOKEN_SECRET);
    req.user = payload;
    next();
} catch (error) {
    if (error.name === 'TokenExpiredError') {
        return res.status(401).json({ error: 'Token expired' });
    }
    return res.status(403).json({ error: 'Invalid token' });
}

}

OAuth 2.0 / OIDC

import { Issuer, generators } from 'openid-client';

// Configure client const issuer = await Issuer.discover('https://accounts.google.com'); const client = new issuer.Client({ client_id: process.env.GOOGLE_CLIENT_ID, client_secret: process.env.GOOGLE_CLIENT_SECRET, redirect_uris: ['https://example.com/callback'], response_types: ['code'], });

// Generate authorization URL app.get('/auth/google', (req, res) => { const codeVerifier = generators.codeVerifier(); const codeChallenge = generators.codeChallenge(codeVerifier);

req.session.codeVerifier = codeVerifier;
req.session.state = generators.state();

const url = client.authorizationUrl({
    scope: 'openid email profile',
    code_challenge: codeChallenge,
    code_challenge_method: 'S256',
    state: req.session.state,
});

res.redirect(url);

});

// Handle callback app.get('/callback', async (req, res) => { const params = client.callbackParams(req); const tokenSet = await client.callback( 'https://example.com/callback', params, { code_verifier: req.session.codeVerifier, state: req.session.state, } );

const userInfo = await client.userinfo(tokenSet.access_token);
// Create session, redirect user

});

Input Validation

import { z } from 'zod';

// Define schema const userSchema = z.object({ email: z.string().email().max(255), password: z.string().min(8).max(100), name: z.string().min(1).max(100).regex(/^[a-zA-Z\s]+$/), age: z.number().int().min(13).max(150).optional(), });

// Validate function validateInput(schema) { return (req, res, next) => { try { req.validated = schema.parse(req.body); next(); } catch (error) { res.status(400).json({ error: 'Validation failed', details: error.errors, }); } }; }

app.post('/users', validateInput(userSchema), createUser);

CSRF Protection

import csrf from 'csurf';

// For traditional forms const csrfProtection = csrf({ cookie: true });

app.get('/form', csrfProtection, (req, res) => { res.render('form', { csrfToken: req.csrfToken() }); });

// For SPAs - use SameSite cookies + custom header // Client sends: X-Requested-With: XMLHttpRequest app.use((req, res, next) => { if (req.method !== 'GET' && req.method !== 'HEAD') { if (req.headers['x-requested-with'] !== 'XMLHttpRequest') { return res.status(403).json({ error: 'CSRF check failed' }); } } next(); });

Security Checklist

Application

  • Use HTTPS everywhere

  • Validate all input (whitelist approach)

  • Encode all output

  • Use parameterized queries

  • Implement proper authentication

  • Implement proper authorization

  • Hash passwords with bcrypt/argon2

  • Use secure session management

  • Set security headers (helmet)

  • Implement rate limiting

  • Log security events

  • Handle errors without leaking info

Infrastructure

  • Keep dependencies updated

  • Use secrets management

  • Configure firewalls

  • Enable audit logging

  • Set up intrusion detection

  • Regular security scans

  • Backup encryption

  • Least privilege access

Development

  • Security code reviews

  • Static analysis (SAST)

  • Dynamic analysis (DAST)

  • Dependency scanning

  • Security training

  • Incident response plan

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Security

wp-security-review

No summary provided by upstream source.

Repository SourceNeeds Review
General

php

No summary provided by upstream source.

Repository SourceNeeds Review
General

laravel

No summary provided by upstream source.

Repository SourceNeeds Review