OWASP ASVS (Application Security Verification Standard)
What is ASVS?
OWASP ASVS (Application Security Verification Standard) is a framework for standardizing security verification of web applications. It provides a comprehensive list of security requirements that developers, testers, and security professionals can reference throughout the design, development, and testing phases of an application.
- Latest stable version: ASVS 4.0 (released 2019), v5.0 (in development)
- Primary goals:
- Clarify implementation standards for security requirements
- Define the depth and scope of security testing
- Serve as a benchmark for procuring and evaluating security controls
- Verify supply chain security
Difference from OWASP Top 10
| Item | OWASP Top 10 | OWASP ASVS |
|---|---|---|
| Purpose | Awareness of most critical risks | Comprehensive security verification standard |
| Scope | 10 threat categories | 14 categories, hundreds of requirements |
| Usage | Risk recognition and prioritization | Design, implementation, and test verification |
| Detail level | Overview | Specific implementation requirements |
Three Verification Levels
ASVS defines three verification levels based on the application's risk profile.
Level 1 - Opportunistic
Minimum security requirements. Covers items that are relatively easy to verify through penetration testing or code review.
- Target: Low-risk applications, proofs of concept (PoC)
- Verification: Penetration testing, automated scanning
- Focus: Defense against "what an attacker would try if given the opportunity"
Level 2 - Standard
The level that most business applications handling sensitive data should achieve. Requires defensive programming and appropriate security controls.
- Target: Apps handling personal or confidential data, e-commerce, business systems
- Verification: Code review, security testing, threat modeling
- Focus: Defense against "what a motivated attacker would try"
Level 3 - Advanced
The highest level of security requirements. Targets healthcare, finance, government, and life-safety systems.
- Target: Healthcare, finance, government, critical infrastructure
- Verification: Thorough code review, design review, architecture verification
- Focus: Defense against "sophisticated targeted attacks"
14 Security Chapters
ASVS is organized into 14 categories (chapters).
V1: Architecture, Design and Threat Modeling
Requirements related to secure design principles and threat modeling.
Key Requirements
- All components are identified and trust boundaries are defined
- Security controls are defined for each component
- Threat models exist for high-value transactions
- Security-related architecture decisions are documented
Example: Implementing Threat Modeling
1. Create a system overview (DFD, etc.)
2. Define trust boundaries
3. Enumerate threats using STRIDE (Spoofing, Tampering, Repudiation, Information Disclosure, DoS, Elevation of Privilege)
4. Assess risks and determine countermeasures
5. Document and continuously review
V2: Authentication
Requirements for properly verifying user identity.
Key Requirements (Level 1)
- Set password length limits (minimum 8 characters) and complexity requirements
- Implement brute-force protections (account lockout, delays, etc.)
- Transmit credentials only over HTTPS
- Do not use default passwords
Key Requirements (Level 2)
- Support multi-factor authentication (MFA)
- Safe implementation of password reset (using time-limited tokens)
- Log all authentication-related events
- Regenerate valid session IDs after successful authentication
Key Requirements (Level 3)
- Support passwordless authentication (WebAuthn, FIDO2)
- Adaptive authentication (risk-based authentication)
// Good: Password hashing with bcrypt
import * as bcrypt from 'bcrypt';
const SALT_ROUNDS = 12; // Sufficient cost factor
async function hashPassword(password: string): Promise<string> {
return bcrypt.hash(password, SALT_ROUNDS);
}
async function verifyPassword(password: string, hash: string): Promise<boolean> {
return bcrypt.compare(password, hash);
}
// Bad (never do this)
// const hash = md5(password); // MD5 is cryptographically broken
// const hash = sha1(password); // SHA-1 is also vulnerable
V3: Session Management
Requirements for proper session management.
Key Requirements (Level 1)
- Session IDs must have at least 128 bits of entropy
- Session IDs must not appear in URLs, logs, or error messages
- Sessions must have idle and absolute timeouts
- Invalidate sessions when a user logs out
Key Requirements (Level 2)
- Regenerate session IDs after authentication (session fixation prevention)
- CSRF protections (double-submit cookie, SynchronizerToken)
- Use cookies with HttpOnly and Secure attributes
- Set the SameSite cookie attribute appropriately
// Good: Secure session configuration (Express.js)
import session from 'express-session';
import crypto from 'crypto';
app.use(session({
secret: process.env.SESSION_SECRET!, // From environment variable
resave: false,
saveUninitialized: false,
genid: () => crypto.randomUUID(), // Sufficient entropy
cookie: {
secure: true, // HTTPS required
httpOnly: true, // Prevent JavaScript access
sameSite: 'strict', // CSRF protection
maxAge: 1000 * 60 * 30, // 30-minute timeout
},
}));
V4: Access Control
Requirements for authorization and permission management.
Key Requirements (Level 1)
- Access control is implemented on all resources
- Directory listing is disabled
- Adopt the principle of Deny by Default
Key Requirements (Level 2)
- Design following the principle of least privilege
- Log all access to sensitive data
- Horizontal access control (prevent access to other users' data)
- Proper implementation of functional access control (RBAC/ABAC)
// Good: RBAC (Role-Based Access Control) implementation
enum Role {
ADMIN = 'admin',
EDITOR = 'editor',
VIEWER = 'viewer',
}
function requireRole(...allowedRoles: Role[]) {
return (req: Request, res: Response, next: NextFunction) => {
const userRole = req.user?.role as Role;
if (!userRole || !allowedRoles.includes(userRole)) {
return res.status(403).json({ error: 'Access denied' });
}
next();
};
}
// Usage
app.delete('/api/users/:id', requireRole(Role.ADMIN), deleteUser);
app.put('/api/articles/:id', requireRole(Role.ADMIN, Role.EDITOR), updateArticle);
app.get('/api/articles/:id', requireRole(Role.ADMIN, Role.EDITOR, Role.VIEWER), getArticle);
V5: Validation, Sanitization and Encoding
Requirements for input validation and output encoding.
Key Requirements (Level 1)
- Treat all inputs as untrusted (comprehensive input validation)
- Defenses against injection attacks (SQLi, XSS, OS Command, etc.)
- Appropriate escaping/encoding based on the output context
- Disable XXE (External Entity) features in XML parsers
// Good: Parameterized queries (SQL injection prevention)
import { Pool } from 'pg';
const pool = new Pool();
// Safe: parameterized query
async function getUserByEmail(email: string) {
const result = await pool.query(
'SELECT id, name, email FROM users WHERE email = $1',
[email] // Pass value via placeholder
);
return result.rows[0];
}
// Dangerous (never use)
// const query = `SELECT * FROM users WHERE email = '${email}'`;
// Good: DOM-based XSS prevention (React)
// React auto-escapes by default, but watch out for dangerouslySetInnerHTML
import DOMPurify from 'dompurify';
function SafeHtmlRenderer({ content }: { content: string }) {
// Do not embed user input directly
const sanitized = DOMPurify.sanitize(content);
return <div dangerouslySetInnerHTML={{ __html: sanitized }} />;
}
V6: Stored Cryptography
Requirements for encrypting data at rest.
Key Requirements
- Use only approved cryptographic algorithms (AES-256, RSA-2048+, etc.)
- Do not use broken algorithms such as MD5 or SHA-1
- Never embed encryption keys in source code
- Use a cryptographically secure pseudo-random number generator (CSPRNG) for random number generation
| Use Case | Recommended Algorithm | Not Recommended |
|---|---|---|
| Symmetric encryption | AES-256-GCM | DES, 3DES, RC4 |
| Asymmetric encryption | RSA-2048+, ECDSA | RSA-1024 or less |
| General hashing | SHA-256+ | MD5, SHA-1 |
| Password hashing | bcrypt, Argon2, scrypt | MD5, SHA-256 (unsalted) |
| Key exchange | ECDH, DHE | Static DH |
// Good: AES-GCM encryption (C#)
using System.Security.Cryptography;
public static (byte[] ciphertext, byte[] nonce, byte[] tag) EncryptAesGcm(
byte[] plaintext, byte[] key)
{
var nonce = new byte[AesGcm.NonceByteSizes.MaxSize]; // 12 bytes
var tag = new byte[AesGcm.TagByteSizes.MaxSize]; // 16 bytes
var ciphertext = new byte[plaintext.Length];
RandomNumberGenerator.Fill(nonce); // Generated by CSPRNG
using var aes = new AesGcm(key, AesGcm.TagByteSizes.MaxSize);
aes.Encrypt(nonce, plaintext, ciphertext, tag);
return (ciphertext, nonce, tag);
}
V7: Error Handling and Logging
Requirements for error handling and log management.
Key Requirements (Level 1)
- Error messages must not include stack traces or internal information
- Customize default error pages
- Log security-relevant events (login success/failure, authorization errors, etc.)
Key Requirements (Level 2)
- Logs must not contain personal data, passwords, or session IDs
- Store logs in write-only storage to prevent tampering
- Security events must include timestamps and sufficient context
- Defend against log injection attacks (sanitize newline characters, etc.)
// Good: Safe error handling (Express.js)
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
// Log internal error info (excluding sensitive data)
logger.error({
message: err.message,
stack: process.env.NODE_ENV === 'development' ? err.stack : undefined,
requestId: req.id,
userId: req.user?.id, // User ID only, no passwords etc.
path: req.path,
});
// Return only a generic message to the client
res.status(500).json({
error: 'Internal server error',
requestId: req.id, // Reference ID for support only
});
});
V8: Data Protection
Requirements for handling sensitive data.
Key Requirements (Level 1)
- Prevent sensitive data from unintentionally leaking into cache, logs, or URLs
- Set appropriate cache-control headers in HTTP responses
- Disable autocomplete on forms containing sensitive data
Key Requirements (Level 2)
- Apply encryption to all sensitive data
- Securely delete old and unnecessary data
- Collect only minimal personal information (data minimization principle)
- Log all access to sensitive data
// Good: HTTP security header configuration (Helmet.js)
import helmet from 'helmet';
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'nonce-{nonce}'"], // CSP Nonce
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", 'data:', 'https:'],
},
},
referrerPolicy: { policy: 'strict-origin-when-cross-origin' },
hsts: {
maxAge: 31536000, // 1 year
includeSubDomains: true,
preload: true,
},
noSniff: true, // X-Content-Type-Options: nosniff
frameguard: { action: 'deny' }, // X-Frame-Options: DENY
}));
V9: Communications
Requirements for communication security.
Key Requirements (Level 1)
- Use TLS 1.2 or higher for all communications
- Validate certificate validity
- Redirect HTTP to HTTPS
Key Requirements (Level 2)
- Disable TLS 1.0 and 1.1
- Disable weak cipher suites (RC4, DES, 3DES, etc.)
- Enable HSTS (HTTP Strict Transport Security)
- Certificate pinning (for high-risk cases)
Recommended TLS configuration (nginx)
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;
add_header Strict-Transport-Security "max-age=63072000" always;
V10: Malicious Code
Requirements for protection against malicious code and backdoors.
Key Requirements
- No malicious logic in source code (time bombs, backdoors, etc.)
- Verification and integrity checking of third-party components
- Implementation of integrity verification mechanisms
V11: Business Logic
Requirements for preventing abuse of business rules.
Key Requirements (Level 1)
- Business logic flows execute only in sequence
- Limits on repeated execution (rate limiting)
- Defenses against misuse by automated tools
Key Requirements (Level 2)
- Anomaly detection for high-value transactions
- Defenses against business logic attacks (negative quantities, integer overflow, etc.)
// Good: Rate limiting implementation (express-rate-limit)
import rateLimit from 'express-rate-limit';
// Brute-force protection for login API
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 10, // Maximum 10 attempts
message: 'Too many login attempts, please try again later.',
standardHeaders: true,
legacyHeaders: false,
skipSuccessfulRequests: true, // Do not count successful requests
});
app.post('/api/auth/login', loginLimiter, loginHandler);
V12: Files and Resources
Requirements for file upload and resource management.
Key Requirements (Level 1)
- Validate uploaded file types (MIME type, magic bytes)
- Store uploaded files outside the web root
- Sanitize file names (path traversal prevention)
Key Requirements (Level 2)
- Virus/malware scanning for uploaded files
- Implement file size limits
- Prevent execution of uploaded files
// Good: File upload validation (Multer)
import multer from 'multer';
import path from 'path';
import { v4 as uuidv4 } from 'uuid';
const ALLOWED_MIME_TYPES = ['image/jpeg', 'image/png', 'image/webp'];
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
const storage = multer.diskStorage({
destination: '/var/app/uploads', // Outside web root
filename: (req, file, cb) => {
// Use random ID instead of original file name (path traversal prevention)
const ext = path.extname(file.originalname).toLowerCase();
cb(null, `${uuidv4()}${ext}`);
},
});
const upload = multer({
storage,
limits: { fileSize: MAX_FILE_SIZE },
fileFilter: (req, file, cb) => {
if (ALLOWED_MIME_TYPES.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new Error('Invalid file type'));
}
},
});
V13: API and Web Service
Requirements for API and web service security.
Key Requirements (Level 1)
- Authentication and authorization properly implemented in REST APIs
- Defenses against known GraphQL and SOAP vulnerabilities
- JSON and XML parsers configured securely
Key Requirements (Level 2)
- API schema validation (leveraging OpenAPI Specification)
- Rate limiting and quota implementation
- Restrict HTTP methods (disable unnecessary ones)
- Proper validation of JWT (JSON Web Token)
// Good: Safe JWT validation
import jwt from 'jsonwebtoken';
function verifyToken(token: string): jwt.JwtPayload {
// Explicitly specify signing algorithm ('none' algorithm attack prevention)
const decoded = jwt.verify(token, process.env.JWT_PUBLIC_KEY!, {
algorithms: ['RS256'], // Explicitly state allowed algorithms
issuer: 'https://auth.example.com',
audience: 'api.example.com',
});
if (typeof decoded === 'string') {
throw new Error('Invalid token payload');
}
return decoded;
}
V14: Configuration
Requirements for security configuration.
Key Requirements (Level 1)
- Disable debug features and developer tools in production
- Remove unnecessary components, features, and pages
- Change default credentials
Key Requirements (Level 2)
- Proper configuration of HTTP security headers
- Implementation of Content Security Policy (CSP)
- Check dependencies for known vulnerabilities (SCA: Software Composition Analysis)
// Good: Security audit with package.json
// Use npm audit, Dependabot, Snyk etc. to regularly check for vulnerabilities
// GitHub Dependabot configuration (.github/dependabot.yml)
// version: 2
// updates:
// - package-ecosystem: "npm"
// directory: "/"
// schedule:
// interval: "weekly"
// open-pull-requests-limit: 10
How to Use ASVS
1. Security Requirements Definition
At project start, select the ASVS level based on the application's risk profile and incorporate it into security requirements.
2. As a Secure Coding Guideline
Incorporate into team coding standards and use as a code review checklist.
| Phase | ASVS Usage |
|---|---|
| Design | Reference V1 (Architecture), V8 (Data Protection) |
| Implementation | Reference V5 (Validation), V6 (Cryptography), V13 (API) |
| Testing | Use each chapter's test cases for test design |
| Deployment | Reference V9 (Communications), V14 (Configuration) |
| Operations | Reference V7 (Logging), V8 (Data Management) |
3. Benchmark for Security Penetration Testing
When commissioning external security firms or penetration testers, present ASVS as the standard for test scope and depth.
4. Mapping to Compliance Standards
ASVS corresponds to major compliance standards.
| Standard | Relationship to ASVS |
|---|---|
| PCI DSS | Level 2 requirements satisfy many PCI DSS requirements |
| GDPR | Strong correspondence with V8 (Data Protection) |
| ISO/IEC 27001 | Corresponds to A.14 (System Acquisition, Development and Maintenance) |
| NIST SP 800-53 | Many controls correspond |
ASVS Checklist (Key Level 1 Items)
Use as a reference for security reviews.
Authentication & Session
- Minimum password length (8 characters, 12 recommended)
- Brute-force protection (account lockout or CAPTCHA)
- Session IDs with at least 128 bits of entropy
- Regenerate session ID after login
- Invalidate sessions server-side on logout
- Cookies have
Secure,HttpOnly, andSameSiteattributes
Access Control & Authorization
- Deny by Default implemented
- Server-side permission checks (not relying only on client-side)
- Horizontal access control (cannot access other users' data)
Input Validation
- All inputs validated server-side
- SQL injection prevention (parameterized queries)
- XSS prevention (output escaping)
- XXE prevention (disable external entities)
Communications & Cryptography
- TLS 1.2+ used for all communications
- Force redirect from HTTP to HTTPS
- HSTS header configured
- No weak cryptographic algorithms (MD5, SHA-1, DES, etc.)
Error Handling & Logging
- Error messages contain no internal information
- Authentication-related events are logged
- Logs do not contain passwords or session IDs
Configuration & Dependencies
- Web server version information is hidden
- Unnecessary HTTP methods disabled (TRACE, etc.)
- Known vulnerabilities in dependency packages checked
- HTTP security headers (X-Content-Type-Options, X-Frame-Options, etc.)
Tools & Resources
Automated Verification Tools
| Category | Tool | Usage |
|---|---|---|
| SAST | Semgrep, CodeQL, Checkmarx | Static analysis of source code |
| DAST | OWASP ZAP, Burp Suite | Dynamic application scanning |
| SCA | Snyk, Dependabot, OWASP Dependency-Check | Dependency vulnerability checks |
| Secret scanning | GitLeaks, TruffleHog | Credential leak detection |
| IaC scanning | Checkov, tfsec, Trivy | Infrastructure code security checks |
Official Resources
Summary
OWASP ASVS is a powerful framework for systematically verifying the security of web applications.
- Level 1: Use as the minimum baseline for all applications
- Level 2: Use as the standard for business systems and apps handling sensitive data
- Level 3: Use for systems requiring high security such as healthcare, finance, and government
By progressively achieving ASVS compliance, you can continuously improve your organization's security maturity. While OWASP Top 10 defines "risks to be aware of," ASVS specifically defines "how to address them," and combining both leads to effective security practices.