Documentation Index
Fetch the complete documentation index at: https://resources.devweekends.com/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Security is not optional. Understanding security fundamentals helps you build systems that protect user data and resist attacks. The 2017 Equifax breach — which exposed 147 million people’s Social Security numbers — happened because of a single unpatched Apache Struts vulnerability that had a fix available for two months. The 2013 Target breach (40 million credit cards stolen) started with compromised HVAC vendor credentials. Security failures are rarely sophisticated; they are almost always a known vulnerability that someone failed to address. The good news: most security problems have well-established solutions. You do not need to be a cryptographer — you need to consistently apply known best practices.Authentication vs Authorization
Authentication (AuthN)
- Verifies identity
- Login, passwords, MFA
- “Prove you are who you claim”
Authorization (AuthZ)
- Verifies permissions
- Roles, policies, ACLs
- “Are you allowed to do this?”
Authentication Methods
Password-Based (Traditional)
Never store passwords in plaintext — not even “temporarily,” not even in logs, not even in a dev database. If your database is breached (and statistically, it will be), properly hashed passwords buy your users time to change their credentials. The algorithm matters: use bcrypt, scrypt, or Argon2 — these are intentionally slow to make brute-force attacks computationally expensive. Fast hashes like MD5 or SHA-256 can be cracked at billions of attempts per second on modern GPUs.JWT (JSON Web Tokens)
OAuth 2.0 Flow
OWASP Top 10 (2021)
The OWASP Top 10 is the industry-standard awareness document for web application security risks, updated every few years based on data from hundreds of organizations. Broken Access Control moved from #5 to #1 in the 2021 edition because it is the most commonly exploited vulnerability class — and the easiest to prevent.1. Broken Access Control
The most dangerous category because it lets attackers access other users’ data or perform admin actions. Also called IDOR (Insecure Direct Object Reference) — the attacker simply changes a user ID in the URL and gets someone else’s data.2. Cryptographic Failures
Using the wrong cryptographic algorithm is as dangerous as using none at all. MD5 was broken in 2004, SHA-1 in 2017. An attacker with a modern GPU can compute 10 billion MD5 hashes per second — meaning any MD5-hashed password under 8 characters can be cracked in under a minute.3. Injection
SQL injection has been the #1 or #2 vulnerability for over 20 years, and it is still being discovered in production systems today. The attack is trivial: ifuser_id is 1; DROP TABLE users; --, your f-string builds a query that deletes your entire users table. Parameterized queries make this attack structurally impossible because the database treats parameters as data, never as executable SQL.
4. Insecure Design
Insecure design is a category new to the 2021 OWASP list. It recognizes that some security flaws are architectural — no amount of perfect implementation can fix a fundamentally insecure design. Security questions (“What is your mother’s maiden name?”) are a classic example: the answers are often public knowledge on social media, making them trivially guessable.5. Security Misconfiguration
The most common misconfiguration is leaving debug mode enabled in production. Debug mode typically exposes stack traces, source code, environment variables, and sometimes an interactive debugger — giving attackers a complete blueprint of your system. Django’s debug page, for instance, shows all settings including database credentials.6. Vulnerable Components
7. Authentication Failures
Without rate limiting, an attacker can try millions of password combinations against your login endpoint. Even with bcrypt, a bot making 1,000 requests per second can test common passwords across thousands of accounts. Rate limiting and account lockout are the first line of defense.Encryption
Symmetric vs Asymmetric
| Type | Key | Speed | Use Case |
|---|---|---|---|
| Symmetric (AES) | Same key | Fast | Data at rest, bulk encryption |
| Asymmetric (RSA) | Public/Private pair | Slow | Key exchange, digital signatures |
HTTPS/TLS
CORS (Cross-Origin Resource Sharing)
CORS is a browser security mechanism that controls which websites can make requests to your API. Without CORS restrictions, a malicious website could make API requests on behalf of your logged-in users (using their cookies). Theallow_origins: ["*"] wildcard effectively disables this protection — any website on the internet can make authenticated requests to your API.
Content Security Policy (CSP)
CSP is the most powerful defense against XSS (Cross-Site Scripting). It tells the browser: “Only execute JavaScript from these specific sources. Block everything else.” Even if an attacker manages to inject a script tag into your page, the browser will refuse to execute it because the script source is not in your CSP whitelist. GitHub’s CSP alone prevented thousands of potential XSS attacks in its first year of deployment.API Security Best Practices
Rate Limiting
API Key Authentication
Security Headers
Security headers are cheap insurance — a few lines of configuration that block entire categories of attacks. Adding these headers takes 10 minutes and prevents clickjacking, MIME confusion attacks, protocol downgrade attacks, and more. Use securityheaders.com to scan your site and verify all headers are properly set.Secrets Management
Environment Variables (Basic)
The simplest secrets management approach: store secrets in environment variables, never in code. This is the bare minimum — suitable for development and simple deployments, but for production systems with multiple services, consider a dedicated secrets manager (Vault, AWS Secrets Manager) that provides audit logging, automatic rotation, and fine-grained access control.HashiCorp Vault (Production)
Vault solves three problems that environment variables cannot: (1) audit logging — you know exactly which service accessed which secret and when, (2) dynamic secrets — database credentials are generated on-the-fly and automatically expire, so there is no long-lived password to steal, and (3) centralized rotation — change a secret in one place, all services pick up the new value.Penetration Testing Checklist
Authentication Testing
Authentication Testing
- Test for default credentials
- Test password policy enforcement
- Test account lockout mechanism
- Test session timeout
- Test “remember me” functionality
- Test password reset flow
- Test MFA bypass attempts
Authorization Testing
Authorization Testing
Injection Testing
Injection Testing
- Test SQL injection (all input fields)
- Test NoSQL injection
- Test Command injection
- Test LDAP injection
- Test XPath injection
- Test template injection (SSTI)
Client-Side Testing
Client-Side Testing
- Test Reflected XSS
- Test Stored XSS
- Test DOM-based XSS
- Test CSRF protection
- Test Clickjacking protection
- Test WebSocket security
Security Checklist
Input Validation
Input Validation
- Validate all user inputs server-side
- Use allowlists, not blocklists
- Sanitize before output (prevent XSS)
- Validate file uploads (type, size, content)
- Use parameterized queries (prevent SQLi)
Authentication
Authentication
- Hash passwords with bcrypt/Argon2 (cost factor ≥12)
- Implement MFA for sensitive operations
- Use secure session management (HttpOnly, Secure, SameSite cookies)
- Rate limit login attempts
- Implement secure password reset (time-limited tokens)
- Consider passwordless authentication (WebAuthn)
Authorization
Authorization
Data Protection
Data Protection
- Encrypt sensitive data at rest (AES-256)
- Use HTTPS everywhere (TLS 1.2+)
- Never log sensitive data (passwords, tokens, PII)
- Implement proper key management and rotation
- Use secure random number generation
- Implement data retention and deletion policies
Infrastructure
Infrastructure
- Keep systems and dependencies updated
- Use WAF (Web Application Firewall)
- Implement network segmentation
- Enable audit logging
- Regular security scanning and penetration testing
- Implement DDoS protection
Common Vulnerabilities Quick Reference
This table covers the vulnerabilities you will encounter most frequently in real-world applications. For each, the prevention is well-established — the challenge is consistently applying it across every endpoint, every input, every dependency.| Vulnerability | Attack Vector | Prevention | Real-World Example |
|---|---|---|---|
| SQL Injection | Malicious SQL in input | Parameterized queries, ORM | 2008 Heartland breach: 130M cards stolen via SQLi |
| XSS | Malicious scripts in pages | Output encoding, CSP | 2005 MySpace Samy worm: 1M friends in 20 hours |
| CSRF | Forged requests | CSRF tokens, SameSite cookies | 2008 Netflix CSRF: attackers changed user account details |
| SSRF | Server-side request to internal | Allowlist URLs, validate input | 2019 Capital One: SSRF on AWS metadata endpoint leaked 100M records |
| XXE | Malicious XML entities | Disable DTD processing | Billion Laughs attack can cause denial of service |
| Path Traversal | ../ in file paths | Validate and sanitize paths | Reads /etc/passwd or application config files |
| Insecure Deserialization | Malicious serialized data | Avoid deserializing untrusted data | 2017 Equifax breach exploited Java deserialization |
Interview Deep-Dive
Your security team discovers that a JWT secret key was accidentally committed to a public GitHub repository 3 days ago. Walk me through your incident response.
Your security team discovers that a JWT secret key was accidentally committed to a public GitHub repository 3 days ago. Walk me through your incident response.
- This is a Severity 1 incident. The exposed secret means anyone who saw it can forge valid JWT tokens for any user in your system, including admin accounts. The blast radius is total authentication compromise.
- Step 1 (immediate, within 15 minutes): Rotate the JWT secret. Generate a new secret and deploy it to all services that verify JWTs. This instantly invalidates every existing token — every user gets logged out. This is inconvenient but necessary. Do not delay rotation to “minimize user impact” — every minute the old secret is active, an attacker can forge tokens.
- Step 2 (within 1 hour): Scrub the secret from Git history. Simply deleting the file and committing does not help —
git logpreserves it forever. Use BFG Repo-Cleaner orgit filter-repoto rewrite history and remove the secret from all commits. Force-push the cleaned history. If the repo is public, assume the secret was already scraped by automated credential harvesting bots (services like GitHub’s secret scanning, TruffleHog, and Gitrob exist specifically for this). - Step 3 (within 4 hours): Audit for unauthorized access. Check your access logs for the past 3 days for suspicious patterns: logins from unusual IPs or geolocations, privilege escalation attempts, bulk data access, or API calls that do not match normal user behavior. If any forged tokens were used, determine what data was accessed and prepare for disclosure.
- Step 4 (within 24 hours): Add guardrails to prevent recurrence. (1) Enable GitHub’s built-in secret scanning (or a pre-commit hook like detect-secrets) that blocks commits containing known secret patterns. (2) Move JWT secrets to a secrets manager (Vault, AWS Secrets Manager) so they are never in code or environment files. (3) Implement JWT key rotation capability — use asymmetric keys (RS256) with a JWKS endpoint so you can rotate keys without redeploying every service.
- Step 5: Conduct a blameless postmortem. How did the secret end up in the repo? Was it a .env file that should have been in .gitignore? A configuration file that was not excluded from version control? Fix the systemic issue, not just the symptom.
A penetration tester reports an IDOR (Insecure Direct Object Reference) vulnerability in your API where changing the order_id in the URL lets any authenticated user view any other user's order. How do you fix this systematically, not just for this one endpoint?
A penetration tester reports an IDOR (Insecure Direct Object Reference) vulnerability in your API where changing the order_id in the URL lets any authenticated user view any other user's order. How do you fix this systematically, not just for this one endpoint?
- IDOR is the most common access control vulnerability (OWASP #1 for a reason), and patching one endpoint is a game of whack-a-mole. The fix must be systemic.
- Immediate fix for the reported endpoint: Add an authorization check that verifies the authenticated user owns the requested resource. In pseudocode:
if order.user_id != current_user.id and not current_user.is_admin: raise 403. This is a 3-line fix. - Systemic fix layer 1: Replace sequential integer IDs with UUIDs for all external-facing identifiers. Sequential IDs (
/orders/1,/orders/2,/orders/3) invite enumeration — an attacker writes a loop from 1 to 10 million. UUIDs (/orders/a1b2c3d4-...) are unguessable, adding a layer of defense-in-depth. This does not replace authorization checks (security through obscurity is not security), but it eliminates casual enumeration. - Systemic fix layer 2: Implement an authorization middleware or decorator that runs on every data-access endpoint. Instead of trusting each developer to remember the authorization check, make it automatic. In a Python/FastAPI application, create a dependency that resolves the resource AND verifies ownership in one step:
def get_order(order_id, current_user) -> Ordereither returns the order (if the user owns it) or raises 403. Every endpoint uses this dependency instead of querying the database directly. - Systemic fix layer 3: Automated testing. Add authorization tests to the CI pipeline that attempt to access resources as the wrong user and assert 403 responses. Use a DAST (Dynamic Application Security Testing) tool like OWASP ZAP in the pipeline that automatically tests for IDOR by replaying authenticated requests with different user sessions.
- Systemic fix layer 4: Default-deny architecture. Instead of each endpoint opting IN to authorization, make authorization the default. Every endpoint requires a policy definition, and if no policy exists, the endpoint returns 403. This ensures new endpoints are secure by default rather than vulnerable by default.
can_access(user, order) = user.id == order.buyer_id OR user.id == order.seller_id OR user.role == 'admin'. For more complex scenarios (a support agent who can view orders from their assigned customers), I would use a policy engine like OPA (Open Policy Agent) or Casbin that evaluates policies defined in a declarative language. The policy definitions live outside the application code — product managers can update access rules without a code deployment. The key design principle: never scatter authorization logic across endpoint handlers. Centralize it in a policy layer that is independently testable, auditable, and changeable.You are designing the authentication system for a new application. Compare session-based auth and JWT-based auth. Which would you choose and why?
You are designing the authentication system for a new application. Compare session-based auth and JWT-based auth. Which would you choose and why?
- Session-based auth: the server creates a session record (in Redis or a database) on login, returns a session ID as a cookie. Every subsequent request sends the cookie, the server looks up the session, and retrieves the user context. The session is the source of truth, stored server-side.
- JWT-based auth: the server creates a signed token containing the user’s identity and claims, returns it to the client. Every subsequent request sends the token, the server verifies the signature and reads the claims. No server-side lookup needed — the token IS the session.
- Session-based advantages: (1) Revocation is instant — delete the session record and the user is logged out immediately. (2) Smaller payload per request — a 32-byte session ID versus a 500-byte JWT. (3) Server has full control — you can change user permissions and it takes effect on the next request.
- JWT-based advantages: (1) Stateless — no shared session store needed, which simplifies horizontal scaling and microservices (any service can verify the token independently). (2) Works well for cross-domain and mobile — no cookie dependency. (3) Reduces database load — no session lookup on every request.
- JWT-based disadvantages that most people underestimate: (1) You cannot revoke a JWT before it expires. If a user’s account is compromised, their token remains valid for its entire lifetime. Workarounds (blocklists, short-lived tokens + refresh tokens) add back the server-side state that JWTs were supposed to eliminate. (2) JWTs grow with claims — adding roles, permissions, and metadata makes them large. (3) Token theft is more dangerous than session theft because the JWT contains everything needed to impersonate the user, while a session ID requires access to the session store.
- My choice depends on the architecture. For a traditional monolithic web application: session-based auth with Redis. Simpler, more secure, and the “stateless” benefit of JWT is irrelevant when you have one server. For a microservices architecture with multiple domains and mobile clients: short-lived JWTs (15 minutes) + server-side refresh tokens (30 days, revocable, stored in a database). This gives you stateless verification for most requests while maintaining the ability to revoke access.
"role": "admin" until it expires. For a 24-hour token, that is 24 hours of unauthorized admin access. For a 15-minute token, the window is smaller but still exists. The trade-off comes down to your security requirements. For a blog platform, a 15-minute window of stale permissions is acceptable. For a financial system, it is not. My approach: store the minimal claim set in the JWT (user_id, token_id, expiry) and fetch permissions from a fast cache (Redis) on each request. The cache lookup adds ~1ms of latency — negligible — and you can update permissions instantly by updating the cache entry. This is a hybrid approach: you get JWT’s stateless verification for authentication (identity) while keeping authorization (permissions) in a mutable, revocable store.Explain the difference between encryption at rest and encryption in transit. A product manager asks if HTTPS is sufficient for security -- what is your response?
Explain the difference between encryption at rest and encryption in transit. A product manager asks if HTTPS is sufficient for security -- what is your response?
- Encryption in transit (HTTPS/TLS) protects data while it is moving between two parties — from the user’s browser to your server, or between two services. It prevents eavesdropping and man-in-the-middle attacks. An attacker sniffing network traffic sees encrypted gibberish instead of plaintext passwords and credit card numbers.
- Encryption at rest protects data where it is stored — on disk, in a database, in backups, in S3 buckets. It prevents an attacker who gains access to the storage medium (stolen hard drive, compromised backup, misconfigured S3 bucket) from reading the data.
- HTTPS alone is NOT sufficient. Here is why: HTTPS protects data between point A and point B. But data is vulnerable at rest at both endpoints. If your database is not encrypted and an attacker gets access to the database files (through a backup leak, a compromised server, or a misconfigured storage volume), they read everything in plaintext. The 2019 Capital One breach exposed 100 million customer records — the data was encrypted in transit but the attacker accessed the unencrypted data at rest through an SSRF vulnerability that reached the AWS metadata service.
- Defense in depth requires both: (1) Encryption in transit: TLS 1.2+ everywhere, including internal service-to-service communication (mTLS in a service mesh). Do not assume your internal network is safe — zero-trust networking means encrypting everything. (2) Encryption at rest: enable storage-level encryption (AWS EBS encryption, RDS encryption, S3 default encryption). For sensitive fields (SSN, credit card numbers), add application-level encryption using envelope encryption — encrypt the data with a data key, encrypt the data key with a master key stored in AWS KMS or Vault. This way, even a database admin who can query the table sees ciphertext. (3) Encryption in use: for the most sensitive data, consider technologies like AWS Nitro Enclaves or homomorphic encryption that protect data even while it is being processed. This is emerging technology, not yet mainstream, but it is the frontier.
- My response to the product manager: “HTTPS is essential but it is one layer. Think of it like locking the door to your house — necessary, but it does not help if someone breaks in through a window. We also need encryption at rest (safe inside the house), strong access controls (who has keys), and monitoring (security cameras). Security is layers, not a single checkbox.”