DevToolBoxGRATIS
Blogg

Web Security Guide: OWASP Top 10, Authentication, XSS, CSRF, CSP & DevSecOps Best Practices

22 min readby DevToolBox Team

TL;DR — Application Security Quick Reference

Application security engineering spans design through deployment. Use parameterized queries to prevent SQLi, CSP to prevent XSS, and SameSite cookies with CSRF tokens to prevent CSRF. Hash passwords with bcrypt/Argon2id, sign JWTs with RS256/EdDSA. Store secrets in Vault or cloud secret managers — never in code. Set HSTS, X-Frame-Options, X-Content-Type-Options, and other security headers. Integrate SAST, DAST, dependency scanning, and container scanning in CI/CD for DevSecOps.

Key Takeaways

  • Always use parameterized queries — never concatenate user input into SQL.
  • Implement CSP headers and output encoding to prevent XSS attacks.
  • Authentication (AuthN) and authorization (AuthZ) must be separate, composable layers.
  • Use Vault or cloud secret managers for secrets — never commit them to version control.
  • Integrate SAST, dependency scanning, and container image scanning in every CI/CD run.
  • Enforce rate limiting, input validation, and CORS whitelisting on all API endpoints.
  • Encrypt data at rest with AES-256-GCM and data in transit with TLS 1.3.
  • Security is a continuous process, not a one-time check — track security debt alongside tech debt.

Application security engineering is more than patching vulnerabilities — it is a systematic approach to embedding security thinking across the entire software development lifecycle. From threat modeling to secure coding, from secrets management to CI/CD security integration, this guide covers everything needed to build secure applications. Whether you are a full-stack developer, backend engineer, or DevOps practitioner, mastering these security practices is essential for protecting user data and business assets.

OWASP Top 10 Overview (2021 Edition)

The OWASP Top 10 is the most widely recognized ranking of web application security risks. The 2021 edition reflects the modern threat landscape with three new categories: Insecure Design, Software and Data Integrity Failures, and SSRF.

IDNameKey Defense
A01Broken Access ControlLeast privilege, RBAC, server-side checks
A02Cryptographic FailuresTLS 1.3, AES-256-GCM, key rotation
A03InjectionParameterized queries, input validation, WAF
A04Insecure DesignThreat modeling, secure design patterns
A05Security MisconfigurationHardened baselines, automated config audits
A06Vulnerable ComponentsDependency scanning, SCA, auto-patching
A07Auth FailuresMFA, rate limiting, secure sessions
A08Integrity FailuresSignature verification, secure CI/CD pipelines
A09Logging FailuresStructured logging, alerting, SIEM
A10SSRFURL allowlists, network segmentation

Authentication & Authorization (AuthN / AuthZ)

Authentication verifies user identity, authorization determines what that user can do. These must be separate layers for flexibility, auditability, and defense in depth.

Password Security

// Password hashing with bcrypt (Node.js)
import bcrypt from 'bcrypt';

const SALT_ROUNDS = 12;

async function hashPassword(plaintext: string): Promise<string> {
  return bcrypt.hash(plaintext, SALT_ROUNDS);
}

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

// Password policy enforcement
function validatePassword(pw: string): string[] {
  const errors: string[] = [];
  if (pw.length < 12) errors.push('Min 12 characters');
  if (!/[A-Z]/.test(pw)) errors.push('Need uppercase');
  if (!/[0-9]/.test(pw)) errors.push('Need digit');
  if (!/[^A-Za-z0-9]/.test(pw)) errors.push('Need special char');
  return errors;
}

JWT Security Best Practices

// JWT with RS256 (asymmetric — recommended)
import jwt from 'jsonwebtoken';
import fs from 'fs';

const privateKey = fs.readFileSync('./keys/private.pem');
const publicKey = fs.readFileSync('./keys/public.pem');

function signToken(payload: object): string {
  return jwt.sign(payload, privateKey, {
    algorithm: 'RS256',
    expiresIn: '15m',    // Short-lived access tokens
    issuer: 'myapp.com',
    audience: 'myapp-api',
  });
}

function verifyToken(token: string): jwt.JwtPayload {
  return jwt.verify(token, publicKey, {
    algorithms: ['RS256'], // CRITICAL: whitelist algorithms
    issuer: 'myapp.com',
    audience: 'myapp-api',
  }) as jwt.JwtPayload;
}

JWT security essentials: always whitelist signing algorithms (disable "none"), use short-lived access tokens with long-lived refresh tokens, validate issuer, audience, and expiration, and store refresh tokens in HttpOnly cookies.

OAuth 2.0 / OIDC Flows

FlowUse CaseSecurity Note
Authorization Code + PKCESPAs, mobile apps, server appsRecommended for all clients
Client CredentialsService-to-service (M2M)Trusted backends only
Device CodeBrowserless devices (CLI, IoT)Short-lived polling codes
Implicit (Legacy)DeprecatedInsecure — migrate to PKCE

RBAC vs ABAC Authorization Models

// RBAC middleware example (Express.js)
type Role = 'admin' | 'editor' | 'viewer';

const permissions: Record<Role, string[]> = {
  admin:  ['read', 'write', 'delete', 'manage_users'],
  editor: ['read', 'write'],
  viewer: ['read'],
};

function requirePermission(permission: string) {
  return (req: Request, res: Response, next: NextFunction) => {
    const userRole = req.user?.role as Role;
    if (!permissions[userRole]?.includes(permission)) {
      return res.status(403).json({ error: 'Forbidden' });
    }
    next();
  };
}

// Usage
app.delete('/api/posts/:id',
  authenticate,
  requirePermission('delete'),
  deletePostHandler
);

Input Validation & Data Sanitization

All user input is untrusted. Validation must be enforced server-side (client-side validation is UX only), and should follow a whitelist-over-blacklist approach.

// Zod schema validation (TypeScript)
import { z } from 'zod';

const CreateUserSchema = z.object({
  email: z.string().email().max(254),
  name: z.string().min(1).max(100)
    .regex(/^[a-zA-Z\s\-']+$/),  // Whitelist chars
  age: z.number().int().min(13).max(150),
  role: z.enum(['user', 'editor']),  // Enum whitelist
  bio: z.string().max(500).optional(),
});

// In route handler
app.post('/api/users', (req, res) => {
  const result = CreateUserSchema.safeParse(req.body);
  if (!result.success) {
    return res.status(400).json({
      error: 'Validation failed',
      details: result.error.flatten(),
    });
  }
  // result.data is typed and validated
  createUser(result.data);
});

Input Validation Checklist

  • Validate type, length, range, and format
  • Use allowlists (whitelists) over blocklists
  • Validate Content-Type headers
  • Apply context-aware encoding for HTML output
  • Normalize Unicode before validation
  • Restrict file upload types, sizes, and storage locations
  • Server-side validation cannot be bypassed — client-side is supplementary

XSS Prevention (Cross-Site Scripting)

XSS attacks inject malicious scripts into pages to steal cookies, hijack sessions, or redirect users. Prevention requires defense in depth with output encoding and CSP.

// Context-aware output encoding
import DOMPurify from 'dompurify';

// HTML context — sanitize user-generated HTML
const safeHTML = DOMPurify.sanitize(userInput, {
  ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p'],
  ALLOWED_ATTR: ['href'],
});

// JavaScript context — NEVER interpolate into JS
// BAD:  <script>var x = "\${userInput}";</script>
// GOOD: Pass data via data attributes or JSON

// URL context — validate scheme
function isSafeUrl(url: string): boolean {
  try {
    const parsed = new URL(url);
    return ['http:', 'https:'].includes(parsed.protocol);
  } catch {
    return false;
  }
}

CSRF Prevention (Cross-Site Request Forgery)

CSRF attacks trick authenticated users into performing unintended actions. Modern prevention combines SameSite cookies with CSRF tokens for double protection.

// Express.js CSRF protection setup
import csrf from 'csurf';
import cookieParser from 'cookie-parser';

app.use(cookieParser());

// Cookie settings for session
app.use(session({
  cookie: {
    httpOnly: true,      // No JS access
    secure: true,        // HTTPS only
    sameSite: 'lax',     // CSRF protection layer 1
    maxAge: 3600000,     // 1 hour
  },
  // ... session store config
}));

// CSRF token middleware (layer 2)
const csrfProtection = csrf({ cookie: true });
app.use(csrfProtection);

// Provide token to client
app.get('/form', (req, res) => {
  res.render('form', { csrfToken: req.csrfToken() });
});

// Token auto-validated on POST/PUT/DELETE
app.post('/transfer', (req, res) => {
  // csrfProtection already verified the token
  processTransfer(req.body);
});

SQL Injection Prevention

SQL injection allows attackers to execute arbitrary database queries. The only reliable defense is parameterized queries — never string concatenation.

// VULNERABLE — never do this
const query = `SELECT * FROM users WHERE id = \${userId}`;

// SAFE — parameterized query (node-postgres)
const { rows } = await pool.query(
  'SELECT * FROM users WHERE id = $1 AND org_id = $2',
  [userId, orgId]
);

// SAFE — ORM (Prisma)
const user = await prisma.user.findUnique({
  where: { id: userId },
  select: { id: true, name: true, email: true },
});

// SAFE — Query builder (Knex)
const users = await knex('users')
  .where({ org_id: orgId })
  .andWhere('created_at', '>', since)
  .select('id', 'name', 'email');

Database Security Hardening

  • Least privilege — application accounts get only needed permissions
  • Use read replicas for reporting queries
  • Enable query logging and slow-query alerting
  • Network segmentation — databases never exposed to public internet
  • Encrypted connections (require SSL/TLS)

Secrets & Credential Management

Leaked secrets are among the most common security incidents. GitHub detects thousands of leaked secrets daily. Proper secrets management is foundational to secure infrastructure.

# .gitignore — MUST include these
.env
.env.*
*.pem
*.key
*.p12
credentials.json
service-account.json

# Pre-commit hook for secret detection
# Install: pip install detect-secrets
# .pre-commit-config.yaml
repos:
  - repo: https://github.com/Yelp/detect-secrets
    rev: v1.4.0
    hooks:
      - id: detect-secrets
        args: ['--baseline', '.secrets.baseline']

Secrets Management Solutions

SolutionTypeBest For
HashiCorp VaultSelf-hosted/CloudLarge orgs, dynamic secrets
AWS Secrets ManagerCloud-nativeAWS ecosystem
GCP Secret ManagerCloud-nativeGCP ecosystem
Azure Key VaultCloud-nativeAzure ecosystem
SOPS + AgeFile encryptionGitOps, small teams
DopplerSaaSMulti-env secret syncing
// Fetching secrets at runtime (Node.js + AWS)
import { SecretsManagerClient,
  GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';

const client = new SecretsManagerClient({ region: 'us-east-1' });

async function getSecret(name: string): Promise<string> {
  const cmd = new GetSecretValueCommand({
    SecretId: name,
  });
  const resp = await client.send(cmd);
  return resp.SecretString ?? '';
}

// Usage — never hardcode secrets
const dbPassword = await getSecret('prod/db/password');

Dependency Scanning & SCA

Software supply chain attacks are increasing. Every dependency is a potential attack surface. Automated dependency scanning should run on every CI build.

# npm audit — built-in Node.js
npm audit --production
npm audit fix

# Snyk — comprehensive SCA
npx snyk test
npx snyk monitor  # continuous monitoring

# pip-audit — Python
pip-audit --require-hashes

# cargo audit — Rust
cargo install cargo-audit
cargo audit

# Trivy — container + filesystem
trivy fs --severity HIGH,CRITICAL .
trivy image myapp:latest

Supply Chain Security Strategies

  • Pin dependency versions (package-lock.json, yarn.lock)
  • Enable Dependabot or Renovate for automated updates
  • Review new dependencies for maintenance status and security history
  • Use Socket.dev to detect suspicious package behavior
  • Consider private registries (Verdaccio, Artifactory)
  • Verify package signatures (npm provenance, sigstore)

Content Security Policy (CSP)

CSP is one of the most effective HTTP headers for preventing XSS. It specifies which resource origins the browser is allowed to load, fundamentally limiting the impact of script injection.

# Strict CSP — recommended starting point
Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-{RANDOM}';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  font-src 'self';
  connect-src 'self' https://api.myapp.com;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';
  upgrade-insecure-requests;

# Nonce-based CSP in Express.js
import crypto from 'crypto';

app.use((req, res, next) => {
  const nonce = crypto.randomBytes(16).toString('base64');
  res.locals.cspNonce = nonce;
  res.setHeader('Content-Security-Policy',
    `default-src 'self'; ` +
    `script-src 'self' 'nonce-\${nonce}'; ` +
    `style-src 'self' 'unsafe-inline'; ` +
    `img-src 'self' data: https:;`
  );
  next();
});

CORS (Cross-Origin Resource Sharing)

CORS controls which external domains can access your API. Misconfigured CORS policies are a common security vulnerability.

// Secure CORS configuration (Express.js)
import cors from 'cors';

// NEVER use: cors({ origin: '*' }) for authenticated APIs

const allowedOrigins = [
  'https://myapp.com',
  'https://admin.myapp.com',
];

app.use(cors({
  origin: (origin, callback) => {
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  },
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true,     // Allow cookies
  maxAge: 86400,         // Preflight cache: 24h
}));

API Security

APIs are the primary attack surface of modern applications. Secure APIs require authentication, authorization, rate limiting, input validation, and proper error handling.

// Rate limiting with sliding window (Express)
import rateLimit from 'express-rate-limit';

// Global rate limit
const globalLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,  // 15 minutes
  max: 100,                   // 100 requests per window
  standardHeaders: true,
  legacyHeaders: false,
});

// Strict limit for auth endpoints
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5,                     // 5 attempts per 15 min
  skipSuccessfulRequests: true,
});

app.use('/api/', globalLimiter);
app.use('/api/auth/login', authLimiter);
app.use('/api/auth/register', authLimiter);

API Security Checklist

LayerMeasureTools/Methods
AuthenticationOAuth 2.0 / JWTAuth0, Clerk, Keycloak
AuthorizationRBAC / ABACCasbin, OPA, Cedar
Rate LimitingSliding window / Token bucketexpress-rate-limit, Redis
Input ValidationSchema validationZod, Joi, AJV
Request LimitsPayload size, query depthbody-parser, graphql-depth-limit
Audit LoggingStructured loggingWinston, Pino, ELK

Encryption: At Rest & In Transit

Encryption protects data from unauthorized access. Transit encryption (TLS) protects network communication, while at-rest encryption protects stored data. Both are foundational for compliance (GDPR, HIPAA, PCI DSS).

Encryption In Transit (TLS)

# Nginx TLS 1.3 configuration
server {
  listen 443 ssl http2;
  server_name myapp.com;

  ssl_certificate     /etc/letsencrypt/live/myapp.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/myapp.com/privkey.pem;

  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:
            ECDHE-RSA-AES128-GCM-SHA256:
            ECDHE-ECDSA-AES256-GCM-SHA384:
            ECDHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers off;

  # HSTS — force HTTPS for 2 years
  add_header Strict-Transport-Security
    "max-age=63072000; includeSubDomains; preload" always;
}

Encryption At Rest

// AES-256-GCM encryption (Node.js)
import crypto from 'crypto';

const ALGORITHM = 'aes-256-gcm';

interface EncryptedData {
  iv: string;
  tag: string;
  ciphertext: string;
}

function encrypt(plaintext: string, key: Buffer): EncryptedData {
  const iv = crypto.randomBytes(12); // 96-bit IV for GCM
  const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
  let ciphertext = cipher.update(plaintext, 'utf8', 'hex');
  ciphertext += cipher.final('hex');
  return {
    iv: iv.toString('hex'),
    tag: cipher.getAuthTag().toString('hex'),
    ciphertext,
  };
}

function decrypt(data: EncryptedData, key: Buffer): string {
  const decipher = crypto.createDecipheriv(
    ALGORITHM, key,
    Buffer.from(data.iv, 'hex')
  );
  decipher.setAuthTag(Buffer.from(data.tag, 'hex'));
  let plaintext = decipher.update(data.ciphertext, 'hex', 'utf8');
  plaintext += decipher.final('utf8');
  return plaintext;
}
ScenarioRecommended AlgorithmNotes
Password hashingArgon2id / bcryptIrreversible, salted
Symmetric encryptionAES-256-GCMAuthenticated encryption, tamper-proof
Asymmetric encryptionRSA-OAEP / X25519Key exchange, digital signatures
Data integrityHMAC-SHA256Verify no tampering
Token signingEdDSA / RS256JWTs, API signatures

Security Headers Configuration

Security headers are among the simplest yet most effective defenses. Properly configured security headers prevent a wide range of common attacks.

// Comprehensive security headers middleware
import helmet from 'helmet';

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'"],
      styleSrc: ["'self'", "'unsafe-inline'"],
      imgSrc: ["'self'", "data:", "https:"],
      connectSrc: ["'self'"],
      fontSrc: ["'self'"],
      frameAncestors: ["'none'"],
    },
  },
  hsts: {
    maxAge: 63072000,  // 2 years
    includeSubDomains: true,
    preload: true,
  },
  referrerPolicy: {
    policy: 'strict-origin-when-cross-origin',
  },
}));

// Additional headers not covered by Helmet
app.use((req, res, next) => {
  res.setHeader('Permissions-Policy',
    'camera=(), microphone=(), geolocation=()');
  res.setHeader('X-Permitted-Cross-Domain-Policies', 'none');
  next();
});

Security Headers Reference

HeaderRecommended ValueProtects Against
Strict-Transport-Securitymax-age=63072000; includeSubDomains; preloadDowngrade attacks, MITM
Content-Security-PolicySee CSP section aboveXSS, data injection
X-Content-Type-OptionsnosniffMIME-type sniffing
X-Frame-OptionsDENYClickjacking
Referrer-Policystrict-origin-when-cross-originInformation leakage
Permissions-Policycamera=(), microphone=(), geolocation=()Feature abuse
Cache-Controlno-store (sensitive pages)Cache poisoning, data leaks

DevSecOps CI/CD Integration

DevSecOps embeds security checks into every stage of the development workflow, achieving "shift-left security" — finding and fixing vulnerabilities as early as possible when the cost is lowest.

# GitHub Actions — security pipeline
name: Security Pipeline
on: [push, pull_request]

jobs:
  secret-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: trufflesecurity/trufflehog@main
        with:
          extra_args: --only-verified

  sast:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: returntocorp/semgrep-action@v1
        with:
          config: >-
            p/security-audit
            p/owasp-top-ten

  dependency-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm audit --audit-level=high
      - uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: \${{ secrets.SNYK_TOKEN }}

  container-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: docker build -t myapp:test .
      - uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:test
          severity: HIGH,CRITICAL
          exit-code: 1

DevSecOps Toolchain

StageToolsChecks
Pre-commitdetect-secrets, git-secrets, truffleHogSecret leak detection
SASTSemgrep, CodeQL, SonarQubeCode vulnerability patterns
SCASnyk, npm audit, DependabotKnown CVE vulnerabilities
Container ScanTrivy, Grype, Snyk ContainerImage vulnerabilities and config
IaC ScanCheckov, tfsec, KICSInfra misconfiguration
DASTOWASP ZAP, Burp Suite, NucleiRuntime vulnerabilities

Security Architecture Patterns

Zero Trust Architecture

The core principle of Zero Trust is "never trust, always verify." Every request must be authenticated, authorized, and encrypted, regardless of whether it originates from inside or outside the network.

  • Micro-segmentation — services communicate via mTLS
  • Verify identity and permissions on every request
  • Least privilege access — grant only what is needed
  • Continuous monitoring and logging — assume breach

Threat Modeling (STRIDE)

ThreatMeaningMitigation
SpoofingImpersonating identityStrong auth, MFA
TamperingModifying dataIntegrity checks, signatures
RepudiationDenying actionsAudit logs, non-repudiation
Info DisclosureExposing informationEncryption, access control
DoSDenial of serviceRate limiting, CDN, auto-scaling
ElevationPrivilege escalationRBAC, least privilege

Security Logging & Monitoring

Without logging and monitoring, security incidents cannot be detected or responded to. Structured logging and real-time alerting are the foundation of security operations.

// Structured security logging (Pino)
import pino from 'pino';

const logger = pino({
  level: 'info',
  redact: ['req.headers.authorization',
           'req.headers.cookie',
           'body.password'],  // Never log secrets
});

// Security event logging
function logSecurityEvent(event: {
  type: string;
  userId?: string;
  ip: string;
  details: string;
  severity: 'low' | 'medium' | 'high' | 'critical';
}) {
  logger.warn({
    securityEvent: true,
    ...event,
    timestamp: new Date().toISOString(),
  });
}

// Example: log failed authentication
logSecurityEvent({
  type: 'AUTH_FAILURE',
  ip: req.ip,
  details: 'Invalid credentials for user@example.com',
  severity: 'medium',
});

Conclusion: Building a Security Culture

Application security is not a one-time task but a continuous engineering practice. From the foundational defenses of the OWASP Top 10 to automated DevSecOps integration, every security layer adds depth to your overall defense. Treat security as a feature, not a burden — the time invested in security pays enormous dividends in preventing data breaches and maintaining user trust.

Action checklist: 1) Enable security headers now; 2) Audit all SQL queries for parameterization; 3) Configure CSP; 4) Add dependency scanning to CI; 5) Implement a secrets management solution; 6) Conduct regular threat modeling and penetration testing. Security is a journey, not a destination.

Frequently Asked Questions

What is the OWASP Top 10 and why does it matter?

The OWASP Top 10 is a regularly updated list of the most critical web application security risks published by the Open Web Application Security Project. It matters because it represents a broad consensus on the most dangerous flaws. Many compliance frameworks (PCI DSS, SOC 2, ISO 27001) reference OWASP as a baseline standard. Addressing the Top 10 significantly reduces your attack surface.

What is the difference between authentication and authorization?

Authentication (AuthN) verifies identity — confirming that a user is who they claim to be through credentials like passwords, tokens, or biometrics. Authorization (AuthZ) determines permissions — what an authenticated user is allowed to do. Authentication answers "who are you?" while authorization answers "what can you access?" Both are required for secure systems, and they should be implemented as separate, composable layers.

How do I prevent SQL injection in modern applications?

Use parameterized queries or prepared statements exclusively — never concatenate user input into SQL strings. ORMs like Prisma, SQLAlchemy, and ActiveRecord use parameterized queries by default. Additionally, apply the principle of least privilege to database accounts, validate and sanitize all inputs, and use a Web Application Firewall (WAF) as an additional defense layer. Regular code reviews and SAST tools can catch injection vulnerabilities early.

What is Content Security Policy (CSP) and how do I implement it?

Content Security Policy is an HTTP response header that controls which resources a browser is allowed to load for a page. A strict CSP prevents XSS by blocking inline scripts and restricting script sources. Start with Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; and tighten from there. Use nonce-based or hash-based CSP for inline scripts instead of 'unsafe-inline'. Report violations with report-uri or report-to directives.

How should I manage secrets like API keys and database passwords?

Never store secrets in source code, environment files committed to version control, or client-side code. Use a dedicated secrets manager such as HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager, or Azure Key Vault. For local development, use .env files that are gitignored. In CI/CD, use pipeline-level secret variables. Rotate secrets regularly, audit access, and use short-lived tokens where possible. Pre-commit hooks with tools like git-secrets or truffleHog can prevent accidental commits of credentials.

What security headers should every web application set?

Essential security headers include: Strict-Transport-Security (HSTS) to enforce HTTPS; Content-Security-Policy to prevent XSS; X-Content-Type-Options: nosniff to prevent MIME-type sniffing; X-Frame-Options: DENY or SAMEORIGIN to prevent clickjacking; Referrer-Policy: strict-origin-when-cross-origin to limit referrer leakage; Permissions-Policy to disable unnecessary browser features; and Cache-Control: no-store for sensitive pages. Use securityheaders.com to audit your configuration.

How do I secure REST APIs against common attacks?

Secure REST APIs by implementing proper authentication (OAuth 2.0, JWT with RS256), rate limiting per endpoint and per user, input validation on all parameters, CORS whitelisting, request size limits, and pagination for list endpoints. Use API keys for identification (not authentication), validate Content-Type headers, return minimal error information to clients, log all access attempts, and version your API to maintain backward compatibility during security updates.

How do I integrate security into a CI/CD pipeline (DevSecOps)?

DevSecOps integrates security checks into every stage of CI/CD. In the commit stage, run pre-commit hooks for secret detection (git-secrets, truffleHog). In the build stage, run SAST tools (Semgrep, CodeQL, SonarQube) and dependency scanning (npm audit, Snyk, Dependabot). In the test stage, run DAST tools (OWASP ZAP, Burp Suite) against staging environments. In the deploy stage, scan container images (Trivy, Grype) and validate Infrastructure as Code (Checkov, tfsec). Fail the pipeline on critical findings and track security debt alongside technical debt.

𝕏 Twitterin LinkedIn
Var dette nyttig?

Hold deg oppdatert

Få ukentlige dev-tips og nye verktøy.

Ingen spam. Avslutt når som helst.

Try These Related Tools

#Hash GeneratorJWTJWT DecoderB→Base64 Encoder

Related Articles

API Rate Limiting Guide: Strategier, Algoritmer og Implementering

Komplett guide til API rate limiting. Token bucket, sliding window, leaky bucket algoritmer med kodeeksempler. Express.js middleware, Redis distribuert rate limiting.

Nettytelsesoptimalisering: Core Web Vitals Guide 2026

Komplett guide til nettytelsesoptimalisering og Core Web Vitals. Forbedre LCP, INP og CLS med praktiske teknikker for bilder, JavaScript, CSS og caching.

Nginx Complete Guide: Server Blocks, Reverse Proxy, Load Balancing, SSL & Performance

Comprehensive Nginx guide covering installation, server blocks, location directives, reverse proxy, load balancing, SSL/TLS, caching, rate limiting, security headers, WebSocket proxy, gzip, and performance tuning with production-ready configurations.