Security Best Practices

Actionable advice and code snippets to harden your web application against common vulnerabilities.

Implement Proper Security Headers

IntermediateHeaders

Security headers are HTTP response headers that, when set, can enhance the security of your web application by enabling browser security policies.

Example Configuration
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: no-referrer-when-downgrade

Always Use HTTPS

BeginnerTransport

HTTPS encrypts the data sent between your users and your website, preventing attackers from intercepting sensitive information.

Implement Content Security Policy (CSP)

AdvancedContent

Content Security Policy is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks.

Example Configuration
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-cdn.com; style-src 'self' https://trusted-cdn.com; img-src 'self' data:;

Secure Your Forms

IntermediateForms

Forms are a common entry point for attacks. Ensure all forms use HTTPS, implement CSRF protection, and validate input both client-side and server-side.

Example Configuration
<form method="POST" action="https://example.com/submit" autocomplete="off">
  <!-- Add CSRF token -->
  <input type="hidden" name="_csrf" value="{{ csrfToken }}" />
  <!-- Other form fields -->
</form>
Recommended Resources

Countries to Consider for Geo-blocking

IntermediateGeo-blocking

Geo-blocking can help prevent attacks from high-risk regions. Consider blocking traffic from countries commonly associated with cyber threats if they are not part of your target audience.

Example Configuration
# Countries commonly associated with cyber threats:
- North Korea (KP)
- China (CN)
- Russia (RU)
- Iran (IR)
- Syria (SY)
- Vietnam (VN)
- Nigeria (NG)
- Belarus (BY)
- Turkey (TR)
Recommended Resources

How to Implement Geo-blocking

AdvancedGeo-blocking

There are several ways to implement geo-blocking depending on your infrastructure.

Example Configuration
# Cloudflare: Use Firewall Rules
# NGINX: Use the geoip module
# .htaccess: Manually block IP ranges by country
# Security Plugins: Many platforms like WordPress offer geo-blocking plugins

Implement Subresource Integrity

IntermediateBest Practices

Subresource Integrity (SRI) is a security feature that enables browsers to verify that resources they fetch are delivered without unexpected manipulation.

Example Configuration
<script src="https://example.com/example-framework.js"
        integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
        crossorigin="anonymous"></script>

Use HTTP Strict Transport Security (HSTS)

BeginnerTransport

HSTS tells browsers to only use HTTPS, preventing protocol downgrade attacks and cookie hijacking.

Example Configuration
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Implement Two-Factor Authentication (2FA)

IntermediateAuthentication

Two-factor authentication adds an extra layer of security by requiring users to provide two forms of identification before accessing their accounts.

Example Configuration
// Example using speakeasy for TOTP
const speakeasy = require('speakeasy');

// Generate secret
const secret = speakeasy.generateSecret({ length: 20 });

// Verify token
const verified = speakeasy.totp.verify({
  secret: secret.base32,
  encoding: 'base32',
  token: userToken
});

Secure Password Storage

IntermediateAuthentication

Never store passwords in plain text. Use strong hashing algorithms like bcrypt, scrypt, or Argon2 with proper salting.

Example Configuration
// Using bcrypt in Node.js
const bcrypt = require('bcrypt');
const saltRounds = 12;

// Hash password
const hash = await bcrypt.hash(password, saltRounds);

// Verify password
const match = await bcrypt.compare(password, hash);

Session Management Best Practices

AdvancedAuthentication

Proper session management prevents session hijacking and fixation attacks. Regenerate session IDs after login, set appropriate timeouts, and invalidate sessions on logout.

Example Configuration
// Express.js session configuration
app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: true,
    httpOnly: true,
    sameSite: 'strict',
    maxAge: 3600000 // 1 hour
  }
}));

API Rate Limiting

IntermediateAPI Security

Rate limiting protects your API from abuse, brute force attacks, and denial of service. Implement limits based on IP, user, or API key.

Example Configuration
// Express rate limiter
const rateLimit = require('express-rate-limit');

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // limit each IP to 100 requests per window
  message: 'Too many requests, please try again later.'
});

app.use('/api/', limiter);

Secure API Authentication with JWT

AdvancedAPI Security

JSON Web Tokens (JWT) provide stateless authentication for APIs. Use short expiration times, secure signing algorithms, and never store sensitive data in the payload.

Example Configuration
// JWT best practices
const jwt = require('jsonwebtoken');

// Sign token with RS256 (asymmetric)
const token = jwt.sign(
  { userId: user.id, role: user.role },
  privateKey,
  { algorithm: 'RS256', expiresIn: '15m' }
);

// Always verify tokens
const decoded = jwt.verify(token, publicKey);

CORS Configuration

IntermediateAPI Security

Cross-Origin Resource Sharing (CORS) controls which domains can access your API. Never use wildcard (*) in production for sensitive endpoints.

Example Configuration
// Express CORS configuration
const cors = require('cors');

const corsOptions = {
  origin: ['https://yourdomain.com', 'https://app.yourdomain.com'],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true,
  maxAge: 86400
};

app.use(cors(corsOptions));
Recommended Resources

Secure Cookie Configuration

BeginnerCookies

Cookies should be configured with security flags to prevent theft and misuse. Always use Secure, HttpOnly, and SameSite attributes.

Example Configuration
Set-Cookie: sessionId=abc123; Secure; HttpOnly; SameSite=Strict; Path=/; Max-Age=3600

// In Express.js
res.cookie('sessionId', 'abc123', {
  secure: true,
  httpOnly: true,
  sameSite: 'strict',
  maxAge: 3600000
});

Cookie Prefixes for Extra Security

AdvancedCookies

Cookie prefixes (__Secure- and __Host-) provide additional security guarantees enforced by browsers.

Example Configuration
// __Secure- prefix: requires Secure flag
Set-Cookie: __Secure-sessionId=abc123; Secure; Path=/

// __Host- prefix: requires Secure, no Domain, Path must be /
Set-Cookie: __Host-sessionId=abc123; Secure; Path=/
Recommended Resources

Prevent SQL Injection

BeginnerDatabase

SQL injection is one of the most common and dangerous vulnerabilities. Always use parameterized queries or prepared statements, never concatenate user input into SQL.

Example Configuration
// BAD - vulnerable to SQL injection
const query = `SELECT * FROM users WHERE id = ${userId}`;

// GOOD - parameterized query
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [userId]);

// GOOD - using ORM (Prisma example)
const user = await prisma.user.findUnique({
  where: { id: userId }
});

Database Connection Security

IntermediateDatabase

Secure your database connections with SSL/TLS, use least-privilege accounts, and never expose databases directly to the internet.

Example Configuration
// PostgreSQL with SSL
const pool = new Pool({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  ssl: {
    rejectUnauthorized: true,
    ca: fs.readFileSync('/path/to/ca-cert.pem')
  }
});

Input Validation and Sanitization

BeginnerBest Practices

Always validate and sanitize user input on both client and server side. Use allowlists over denylists when possible.

Example Configuration
// Using Zod for validation
import { z } from 'zod';

const userSchema = z.object({
  email: z.string().email(),
  age: z.number().min(18).max(120),
  username: z.string().min(3).max(20).regex(/^[a-zA-Z0-9_]+$/)
});

// Validate input
const result = userSchema.safeParse(userInput);