OWASP Top 10 for Developers: Understanding and Eliminating the Most Critical Web Application Risks
The OWASP Top 10 defines the most critical security risks in web applications. This developer-focused guide explains each category, shows how vulnerabilities arise in real code, and provides concrete remediation steps.
The Open Web Application Security Project (OWASP) Top 10 is the most widely referenced framework for web application security. Updated periodically to reflect the current threat landscape, it identifies the ten most critical security risk categories affecting web applications — the vulnerabilities that appear most frequently in real-world breaches and that carry the highest potential for damage.
For developers, the Top 10 is not just a compliance checklist. It is a practical map of where applications break, why they break, and what to do about it. This guide walks through each category with a developer's lens: how the vulnerability arises, what an attacker does with it, and how to eliminate it.
A01: Broken Access Control
Access control enforces that users can only perform actions and access data they are authorised for. Broken access control is the most prevalent category in the current Top 10, appearing in 94% of tested applications.
How it arises: Access control logic is often implemented inconsistently — enforced in the UI but not in the API, applied to some routes but not others, or based on client-supplied data that can be manipulated.
Common patterns:
- Insecure Direct Object References (IDOR): a URL like
/api/invoices/1042returns data for any authenticated user, not just the invoice owner - Missing function-level access control: admin endpoints are hidden from the UI but accessible directly
- Privilege escalation: a user modifies a request parameter to act as a different user or role
What attackers do: Enumerate object IDs to access other users' data, call privileged API endpoints directly, or modify account parameters to escalate their own privileges.
Remediation:
- Enforce access control server-side on every request — never rely on client-side checks alone
- Implement a centralised authorisation module rather than scattering checks across handlers
- Default to deny: if a user's permission to access a resource is not explicitly granted, deny the request
- Log access control failures and alert on patterns that suggest enumeration
A02: Cryptographic Failures
Previously called "Sensitive Data Exposure," this category covers failures in cryptography that expose sensitive data — passwords, financial records, health information, session tokens.
How it arises: Developers often use cryptography incorrectly: outdated algorithms, weak key lengths, missing encryption for data in transit, or storing sensitive data in plaintext.
Common patterns:
- Passwords stored as MD5 or SHA-1 hashes (both are fast-hash algorithms unsuitable for passwords)
- HTTP used instead of HTTPS for pages handling sensitive data
- Sensitive data stored in browser localStorage or URL parameters
- Encryption keys hardcoded in source code
What attackers do: Intercept unencrypted traffic, crack weak password hashes offline, or extract keys from source code repositories.
Remediation:
- Use bcrypt, Argon2, or scrypt for password hashing — never MD5, SHA-1, or SHA-256 alone
- Enforce HTTPS everywhere; use HSTS to prevent downgrade attacks
- Encrypt sensitive data at rest using AES-256 or equivalent
- Store encryption keys in a secrets manager (AWS Secrets Manager, HashiCorp Vault), never in code or environment variables committed to version control
- Classify data by sensitivity and apply appropriate controls to each tier
A03: Injection
Injection vulnerabilities occur when untrusted data is sent to an interpreter — a database, shell, LDAP server, or XML parser — as part of a command or query. SQL injection is the most well-known variant, but the category includes OS command injection, LDAP injection, and others.
How it arises: String concatenation to build queries or commands using user-supplied input.
// Vulnerable
const query = `SELECT * FROM users WHERE email = '${req.body.email}'`;
// An attacker submits: ' OR '1'='1
// Resulting query: SELECT * FROM users WHERE email = '' OR '1'='1'
// Returns all users
What attackers do: Extract entire database contents, bypass authentication, modify or delete data, or in some configurations execute operating system commands.
Remediation:
- Use parameterised queries or prepared statements — never string concatenation for queries
- Use an ORM (Drizzle, Prisma, Sequelize) that handles parameterisation by default
- Validate and sanitise all input, but treat this as defence-in-depth, not the primary control
- Apply least privilege to database accounts: the application user should not have DROP or admin privileges
- For OS commands, avoid shell execution entirely where possible; use language-native APIs instead
A04: Insecure Design
This category addresses architectural and design-level security failures — flaws that exist before a single line of code is written. It was added to the Top 10 in 2021 to reflect the growing recognition that many vulnerabilities cannot be fixed by patching code; they require redesigning the system.
How it arises: Security is not considered during requirements and design phases. Threat modelling is skipped. Business logic is implemented without considering how it could be abused.
Common patterns:
- Password reset flows that rely on security questions rather than cryptographic tokens
- Rate limiting absent from authentication endpoints, enabling credential stuffing
- Business logic that allows negative quantities in e-commerce orders
- Multi-step workflows where steps can be skipped by manipulating requests
What attackers do: Abuse business logic in ways the developers never anticipated, bypass multi-factor authentication, or exploit the absence of rate limiting to enumerate accounts or brute-force credentials.
Remediation:
- Conduct threat modelling during design: for each feature, ask "how could an attacker abuse this?"
- Establish secure design patterns and reference architectures for common flows (authentication, password reset, payment)
- Implement rate limiting on all authentication and sensitive endpoints
- Validate business logic server-side: never trust the client to enforce ordering, quantities, or state transitions
A05: Security Misconfiguration
Security misconfiguration is the most commonly found issue in practice. It covers a broad range of failures: default credentials left unchanged, unnecessary features enabled, verbose error messages exposing stack traces, missing security headers, and cloud storage buckets left publicly accessible.
How it arises: Default configurations prioritise ease of use over security. Developers and operations teams under time pressure skip hardening steps. Infrastructure is provisioned through manual processes that are inconsistently applied.
Common patterns:
- Default admin credentials on databases, admin panels, or network devices
- Stack traces and detailed error messages returned to end users
- Directory listing enabled on web servers
- S3 buckets or Azure Blob Storage containers set to public read
- Missing HTTP security headers (Content-Security-Policy, X-Frame-Options, HSTS)
- Unnecessary services or ports exposed
What attackers do: Log in with default credentials, extract sensitive information from error messages, access publicly exposed storage, or exploit enabled but unneeded services.
Remediation:
- Automate infrastructure provisioning with hardened baseline configurations (Infrastructure as Code)
- Disable or remove all features, services, and accounts not actively needed
- Return generic error messages to users; log detailed errors server-side only
- Implement a security headers policy and verify it with tools like securityheaders.com
- Regularly audit cloud storage permissions
- Run automated configuration scanning tools (AWS Config, Azure Security Center, Lynis for Linux)
A06: Vulnerable and Outdated Components
Modern applications are built on a foundation of third-party libraries, frameworks, and dependencies. Each dependency is a potential source of vulnerabilities. This category covers the risk of running components with known security flaws.
How it arises: Dependencies are added and forgotten. No process exists to monitor for new CVEs affecting the dependency tree. Upgrading is deferred because it might break things.
What attackers do: Scan for applications running known-vulnerable versions of popular libraries and exploit published CVEs. This is largely automated — tools like Shodan and Censys make it trivial to find internet-facing systems running vulnerable software at scale.
Remediation:
- Maintain a software bill of materials (SBOM) — a complete inventory of all dependencies and their versions
- Use automated dependency scanning tools: npm audit, Snyk, Dependabot, OWASP Dependency-Check
- Subscribe to CVE feeds for your key dependencies
- Establish a patch SLA: critical CVEs in production dependencies should be remediated within 24–72 hours
- Remove unused dependencies — every library you do not need is a vulnerability you do not have to manage
A07: Identification and Authentication Failures
This category covers weaknesses in how applications verify user identity and manage sessions. It includes weak password policies, missing multi-factor authentication, insecure session management, and credential stuffing vulnerabilities.
How it arises: Authentication is often implemented from scratch rather than using battle-tested libraries. Session tokens are generated with insufficient entropy. Password policies are weak. MFA is optional or absent.
Common patterns:
- Session tokens that do not expire or are not invalidated on logout
- Passwords stored without salting, enabling rainbow table attacks
- No account lockout or rate limiting on login endpoints
- Session IDs transmitted in URLs (logged by servers and proxies)
- Accepting weak or commonly used passwords
What attackers do: Conduct credential stuffing attacks using leaked username/password pairs from other breaches, brute-force weak passwords, or hijack sessions through token prediction or theft.
Remediation:
- Use a well-maintained authentication library rather than building from scratch (Passport.js, BetterAuth, Auth.js)
- Enforce MFA for all privileged accounts; offer it to all users
- Implement rate limiting and account lockout on authentication endpoints
- Generate session tokens with cryptographically secure random number generators; use sufficient entropy (128 bits minimum)
- Invalidate sessions on logout and after password changes
- Check passwords against known-breached password lists (Have I Been Pwned API)
A08: Software and Data Integrity Failures
This category covers failures to verify the integrity of software updates, critical data, and CI/CD pipelines. It includes insecure deserialisation and supply chain attacks where malicious code is introduced through a trusted dependency or build process.
How it arises: Applications deserialise untrusted data without verification. CI/CD pipelines pull dependencies from public registries without integrity checks. Auto-update mechanisms do not verify signatures.
The SolarWinds attack — where malicious code was inserted into a software build process and distributed to thousands of organisations through a trusted update — is the defining example of this category at scale.
What attackers do: Inject malicious code through compromised dependencies, manipulate deserialised objects to achieve remote code execution, or tamper with software update mechanisms.
Remediation:
- Use digital signatures to verify software and updates
- Implement subresource integrity (SRI) for CDN-hosted scripts
- Avoid deserialising data from untrusted sources; if deserialisation is necessary, use safe formats (JSON with schema validation) rather than native object serialisation
- Audit CI/CD pipeline permissions; apply least privilege to build systems
- Pin dependency versions and verify checksums; use lockfiles
- Monitor for unexpected changes to build configurations or dependency trees
A09: Security Logging and Monitoring Failures
Insufficient logging and monitoring means that breaches go undetected, investigations cannot be completed, and attackers have more time to achieve their objectives. Studies consistently show that the average time between initial compromise and detection is measured in weeks or months.
How it arises: Logging is treated as an afterthought. Security-relevant events are not logged. Logs are not monitored or alerted on. Log data is not retained long enough for forensic investigation.
What attackers do: Operate undetected for extended periods, covering their tracks by deleting logs if they have sufficient access, and achieving their objectives before anyone notices.
Remediation:
- Log all authentication events (successes and failures), access control failures, and input validation failures
- Include sufficient context in logs: timestamp, user identity, IP address, action, outcome
- Centralise logs in a SIEM or log management platform; do not rely on application-level logs alone
- Set up alerts for patterns that indicate attack activity: repeated authentication failures, access control violations, unusual data access volumes
- Retain logs for a minimum of 12 months (longer for regulated industries)
- Protect log integrity: logs should be written to append-only storage that application processes cannot modify
A10: Server-Side Request Forgery (SSRF)
SSRF vulnerabilities allow attackers to induce the server to make HTTP requests to an arbitrary destination — including internal services that are not accessible from the internet. As applications increasingly integrate with external services and run in cloud environments with rich internal metadata APIs, SSRF has become a critical risk.
How it arises: Applications fetch resources from URLs supplied by users without validating that the destination is permitted.
// Vulnerable: fetches a URL provided by the user
app.get('/preview', async (req, res) => {
const content = await fetch(req.query.url);
res.send(content);
});
// An attacker submits: ?url=http://169.254.169.254/latest/meta-data/
// On AWS, this returns EC2 instance metadata including IAM credentials
What attackers do: Access cloud provider metadata APIs to steal IAM credentials, probe internal services (databases, admin interfaces, internal APIs) that are not internet-facing, or pivot to internal network resources.
Remediation:
- Validate and allowlist URLs before fetching: only permit specific domains or URL patterns
- Block requests to private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and link-local addresses (169.254.0.0/16)
- Disable HTTP redirects in fetch clients, or validate the final destination after redirects
- Use network-level controls to prevent application servers from making unexpected outbound connections
- In cloud environments, use IMDSv2 (which requires a session token) to mitigate metadata API abuse
Integrating OWASP Top 10 Into Your Development Process
Awareness of the Top 10 is the starting point, not the destination. The goal is to build security into the development process so that these vulnerabilities are caught before they reach production.
Shift left: Introduce security earlier in the development lifecycle. Static application security testing (SAST) tools like Semgrep, SonarQube, and CodeQL can be integrated into CI/CD pipelines to flag vulnerable code patterns automatically on every commit.
Dynamic testing: Dynamic application security testing (DAST) tools like OWASP ZAP and Burp Suite test running applications for vulnerabilities. Automated DAST scans in staging environments catch issues that static analysis misses.
Developer training: The most cost-effective security investment is teaching developers to write secure code in the first place. Regular training on secure coding practices, combined with code review processes that include security checks, prevents vulnerabilities from being introduced.
Penetration testing: Regular penetration testing — both automated and manual — validates that your controls are working and finds the vulnerabilities that automated tools miss. Manual testing is particularly valuable for business logic flaws (A04) and access control issues (A01) that require contextual understanding.
Dependency management: Automated dependency scanning (Snyk, Dependabot) integrated into your CI/CD pipeline ensures that known-vulnerable components (A06) are flagged before they reach production.
Conclusion
The OWASP Top 10 represents the most impactful security improvements a development team can make. These are not exotic, nation-state-level threats — they are the vulnerabilities that appear in real applications, exploited by real attackers, causing real damage every day.
The good news is that most of them are preventable with well-understood techniques: parameterised queries, proper access control, strong cryptography, dependency management, and comprehensive logging. The challenge is consistency — applying these practices across every feature, every endpoint, and every release.
XcodeFactory builds security into the development process from the start, not as a bolt-on after the fact. If you are building a web application and want to ensure it is hardened against the OWASP Top 10 and beyond, contact our team to discuss a security-first development engagement.
Explore Topics
Written by
XcodeFactory Team
Content creator and writer sharing insights and stories.
