security-best-practices
Provides security best practices, guiding new projects to consider security from the outset, and conducting security audits and API hardening.
npx skills add supercent-io/skills-template --skill security-best-practicesBefore / After Comparison
1 组In the early stages of project development, security issues are often overlooked, leading to high repair costs when vulnerabilities are discovered later. The lack of systematic security audits and API hardening measures exposes projects to potential cyberattack risks, affecting user trust and business continuity.
With the security-best-practices skill, security considerations are integrated into projects from the outset. By guiding security audits and API hardening, potential threats are effectively prevented. This ensures that projects possess robust security protection capabilities throughout their entire lifecycle.
security-best-practices
Security Best Practices
When to use this skill
-
New project: consider security from the start
-
Security audit: inspect and fix vulnerabilities
-
Public API: harden APIs accessible externally
-
Compliance: comply with GDPR, PCI-DSS, etc.
Instructions
Step 1: Enforce HTTPS and security headers
Express.js security middleware:
import express from 'express';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
const app = express();
// Helmet: automatically set security headers
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'", "https://trusted-cdn.com"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
connectSrc: ["'self'", "https://api.example.com"],
fontSrc: ["'self'", "https:", "data:"],
objectSrc: ["'none'"],
mediaSrc: ["'self'"],
frameSrc: ["'none'"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
}));
// Enforce HTTPS
app.use((req, res, next) => {
if (process.env.NODE_ENV === 'production' && !req.secure) {
return res.redirect(301, `https://${req.headers.host}${req.url}`);
}
next();
});
// Rate limiting (DDoS prevention)
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // max 100 requests per IP
message: 'Too many requests from this IP, please try again later.',
standardHeaders: true,
legacyHeaders: false,
});
app.use('/api/', limiter);
// Stricter for auth endpoints
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5, // only 5 times per 15 minutes
skipSuccessfulRequests: true // do not count successful requests
});
app.use('/api/auth/login', authLimiter);
Step 2: Input validation (SQL Injection, XSS prevention)
Joi validation:
import Joi from 'joi';
const userSchema = Joi.object({
email: Joi.string().email().required(),
password: Joi.string().min(8).pattern(/^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/).required(),
name: Joi.string().min(2).max(50).required()
});
app.post('/api/users', async (req, res) => {
// 1. Validate input
const { error, value } = userSchema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
// 2. Prevent SQL Injection: Parameterized Queries
// ❌ Bad example
// db.query(`SELECT * FROM users WHERE email = '${email}'`);
// ✅ Good example
const user = await db.query('SELECT * FROM users WHERE email = ?', [value.email]);
// 3. Prevent XSS: Output Encoding
// React/Vue escape automatically; otherwise use a library
import DOMPurify from 'isomorphic-dompurify';
const sanitized = DOMPurify.sanitize(userInput);
res.json({ user: sanitized });
});
Step 3: Prevent CSRF
CSRF Token:
import csrf from 'csurf';
import cookieParser from 'cookie-parser';
app.use(cookieParser());
// CSRF protection
const csrfProtection = csrf({ cookie: true });
// Provide CSRF token
app.get('/api/csrf-token', csrfProtection, (req, res) => {
res.json({ csrfToken: req.csrfToken() });
});
// Validate CSRF on all POST/PUT/DELETE requests
app.post('/api/*', csrfProtection, (req, res, next) => {
next();
});
// Use on the client
// fetch('/api/users', {
// method: 'POST',
// headers: {
// 'CSRF-Token': csrfToken
// },
// body: JSON.stringify(data)
// });
Step 4: Manage secrets
.env (never commit):
# Database
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
# JWT
ACCESS_TOKEN_SECRET=your-super-secret-access-token-key-min-32-chars
REFRESH_TOKEN_SECRET=your-super-secret-refresh-token-key-min-32-chars
# API Keys
STRIPE_SECRET_KEY=sk_test_xxx
SENDGRID_API_KEY=SG.xxx
Kubernetes Secrets:
apiVersion: v1
kind: Secret
metadata:
name: myapp-secrets
type: Opaque
stringData:
database-url: postgresql://user:password@postgres:5432/mydb
jwt-secret: your-jwt-secret
// Read from environment variables
const dbUrl = process.env.DATABASE_URL;
if (!dbUrl) {
throw new Error('DATABASE_URL environment variable is required');
}
Step 5: Secure API authentication
JWT + Refresh Token Rotation:
// Short-lived access token (15 minutes)
const accessToken = jwt.sign({ userId }, ACCESS_SECRET, { expiresIn: '15m' });
// Long-lived refresh token (7 days), store in DB
const refreshToken = jwt.sign({ userId }, REFRESH_SECRET, { expiresIn: '7d' });
await db.refreshToken.create({
userId,
token: refreshToken,
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
});
// Refresh token rotation: re-issue on each use
app.post('/api/auth/refresh', async (req, res) => {
const { refreshToken } = req.body;
const payload = jwt.verify(refreshToken, REFRESH_SECRET);
// Invalidate existing token
await db.refreshToken.delete({ where: { token: refreshToken } });
// Issue new tokens
const newAccessToken = jwt.sign({ userId: payload.userId }, ACCESS_SECRET, { expiresIn: '15m' });
const newRefreshToken = jwt.sign({ userId: payload.userId }, REFRESH_SECRET, { expiresIn: '7d' });
await db.refreshToken.create({
userId: payload.userId,
token: newRefreshToken,
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
});
res.json({ accessToken: newAccessToken, refreshToken: newRefreshToken });
});
Constraints
Required rules (MUST)
-
HTTPS Only: HTTPS required in production
-
Separate secrets: manage via environment variables; never hardcode in code
-
Input Validation: validate all user input
-
Parameterized Queries: prevent SQL Injection
-
Rate Limiting: DDoS prevention
Prohibited items (MUST NOT)
-
No eval(): code injection risk
-
No direct innerHTML: XSS risk
-
No committing secrets: never commit .env files
OWASP Top 10 checklist
- [ ] A01: Broken Access Control - RBAC, authorization checks
- [ ] A02: Cryptographic Failures - HTTPS, encryption
- [ ] A03: Injection - Parameterized Queries, Input Validation
- [ ] A04: Insecure Design - Security by Design
- [ ] A05: Security Misconfiguration - Helmet, change default passwords
- [ ] A06: Vulnerable Components - npm audit, regular updates
- [ ] A07: Authentication Failures - strong auth, MFA
- [ ] A08: Data Integrity Failures - signature validation, CSRF prevention
- [ ] A09: Logging Failures - security event logging
- [ ] A10: SSRF - validate outbound requests
Best practices
-
Principle of Least Privilege: grant minimal privileges
-
Defense in Depth: layered security
-
Security Audits: regular security reviews
References
Metadata
Version
-
Current version: 1.0.0
-
Last updated: 2025-01-01
-
Compatible platforms: Claude, ChatGPT, Gemini
Related skills
Tags
#security #OWASP #HTTPS #CORS #XSS #SQL-injection #CSRF #infrastructure
Examples
Example 1: Basic usage
Example 2: Advanced usage
Weekly Installs13.0KRepositorysupercent-io/sk…templateGitHub Stars58First SeenJan 24, 2026Security AuditsGen Agent Trust HubPassSocketPassSnykPassInstalled oncodex12.8Kgemini-cli12.8Kopencode12.8Kgithub-copilot12.8Kcursor12.8Kamp12.7K
User Reviews (0)
Write a Review
No reviews yet
Statistics
User Rating
Rate this Skill