Security Testing
Purpose
Provide a comprehensive security testing methodology covering authentication, authorization, input validation, injection prevention, data protection, and OWASP Top 10 compliance. This skill identifies vulnerabilities across the application stack and validates that security measures are correctly implemented.
When to Use
- •Before production deployment
- •After implementing authentication or authorization
- •When handling sensitive data (PII, payments)
- •After security-related code changes
- •As part of regular security assessments
- •When adding new API endpoints or user inputs
Process
Step 1: Authentication Testing
Objective: Verify authentication mechanisms are secure.
Tests:
- •Valid authentication succeeds
- •Invalid credentials are rejected
- •Brute force protection is active (rate limiting)
- •Session management is secure
- •Token expiration is enforced
- •Password policies are enforced
- •Logout invalidates sessions/tokens
- •OAuth/SSO flows are correctly implemented
Example:
describe('Authentication Security', () => {
it('should reject invalid credentials', async () => {
const response = await app.request('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'user@example.com',
password: 'wrongpassword',
}),
});
expect(response.status).toBe(401);
});
it('should rate limit failed login attempts', async () => {
for (let i = 0; i < 10; i++) {
await app.request('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'user@example.com', password: 'wrong' }),
});
}
const response = await app.request('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'user@example.com', password: 'wrong' }),
});
expect(response.status).toBe(429);
});
it('should reject invalid JWT tokens', async () => {
const response = await app.request('/api/protected', {
headers: { Authorization: 'Bearer invalid-token-value' },
});
expect(response.status).toBe(401);
});
});
Step 2: Authorization Testing
Objective: Ensure proper access control and permissions.
Tests:
- •Role-based access control (RBAC) enforcement
- •Resource ownership validation
- •Privilege escalation prevention
- •Horizontal access control (user A cannot access user B resources)
- •Vertical access control (regular users cannot access admin endpoints)
Example:
describe('Authorization Security', () => {
it('should prevent users from accessing other users resources', async () => {
const userAToken = await getAuthToken('user-a');
const response = await app.request('/api/resources/user-b-resource-id', {
headers: { Authorization: `Bearer ${userAToken}` },
});
expect(response.status).toBe(403);
});
it('should require admin role for admin endpoints', async () => {
const regularUserToken = await getAuthToken('regular-user');
const response = await app.request('/api/admin/users', {
headers: { Authorization: `Bearer ${regularUserToken}` },
});
expect(response.status).toBe(403);
});
});
Step 3: Input Validation Testing
Objective: Prevent injection attacks and malicious input.
SQL Injection:
it('should prevent SQL injection', async () => {
const maliciousInput = "'; DROP TABLE users; --";
const response = await app.request(
`/api/search?q=${encodeURIComponent(maliciousInput)}`
);
expect(response.status).toBe(200);
// Verify database is intact
const usersExist = await db.users.count();
expect(usersExist).toBeGreaterThan(0);
});
XSS Prevention:
it('should prevent XSS attacks', async () => {
const xssPayload = '<script>alert("XSS")</script>';
const response = await app.request('/api/comments', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content: xssPayload }),
});
const data = await response.json();
expect(data.content).not.toContain('<script>');
});
Additional input validation tests:
- •Command injection payloads
- •Path traversal attempts (../../etc/passwd)
- •Type confusion attacks
- •Boundary value abuse
- •Oversized payloads
Step 4: Data Protection Testing
Objective: Ensure sensitive data is properly protected.
describe('Data Protection', () => {
it('should not expose sensitive fields in API responses', async () => {
const response = await app.request('/api/users/profile', {
headers: { Authorization: `Bearer ${validToken}` },
});
const user = await response.json();
expect(user).not.toHaveProperty('password');
expect(user).not.toHaveProperty('passwordHash');
expect(user).not.toHaveProperty('resetToken');
});
it('should not leak internal details in error messages', async () => {
const response = await app.request('/api/users/non-existent');
expect(response.status).toBe(404);
const error = await response.json();
expect(error.message).not.toContain('database');
expect(error.message).not.toContain('SQL');
expect(error).not.toHaveProperty('stack');
});
});
Step 5: API Security Testing
Objective: Validate API-specific security measures.
describe('API Security', () => {
it('should include security headers', async () => {
const response = await app.request('/api/resources');
expect(response.headers.get('X-Content-Type-Options')).toBe('nosniff');
expect(response.headers.get('X-Frame-Options')).toBe('DENY');
expect(response.headers.get('Content-Security-Policy')).toBeTruthy();
});
it('should enforce CORS policy', async () => {
const response = await app.request('/api/resources', {
headers: { Origin: 'https://malicious-site.com' },
});
expect(response.headers.get('Access-Control-Allow-Origin')).not.toBe('*');
});
it('should enforce request size limits', async () => {
const largePayload = 'x'.repeat(10 * 1024 * 1024); // 10MB
const response = await app.request('/api/resources', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ data: largePayload }),
});
expect(response.status).toBe(413);
});
});
Step 6: Dependency Security
Objective: Identify vulnerable dependencies.
- •Run package audit tools (npm audit, pnpm audit, yarn audit)
- •Review security advisories for critical packages
- •Verify no known CVEs affect the project
- •Update or patch vulnerable dependencies
# Check for vulnerabilities npm audit --audit-level moderate pnpm audit --audit-level moderate
OWASP Top 10 Coverage Checklist
- •A01 - Broken Access Control: Authorization tests, resource ownership
- •A02 - Cryptographic Failures: HTTPS enforcement, password hashing, encryption
- •A03 - Injection: SQL injection, XSS, command injection tests
- •A04 - Insecure Design: Security by design, threat modeling
- •A05 - Security Misconfiguration: Headers, CORS, default configs
- •A06 - Vulnerable Components: Dependency scanning, CVE monitoring
- •A07 - Authentication Failures: Login, session, token tests
- •A08 - Data Integrity Failures: Input validation, deserialization
- •A09 - Logging Failures: No secrets in logs, audit trails
- •A10 - SSRF: URL validation, outbound request restrictions
Best Practices
- •Defense in depth -- implement multiple security layers
- •Fail securely -- default to denying access
- •Least privilege -- grant only the minimum required permissions
- •Validate all input -- never trust client-side data
- •Encode output -- prevent XSS by encoding rendered data
- •Use parameterized queries -- prevent SQL injection
- •Set security headers -- CSP, HSTS, X-Frame-Options, etc.
- •Audit regularly -- run security scans continuously
- •Keep dependencies current -- patch known vulnerabilities promptly
- •Log security events -- monitor for suspicious activity
- •Never trust client-side validation alone -- always validate server-side
- •Automate in CI/CD -- run security tests on every build
Output
When applying this skill, produce:
- •Security test suite covering authentication, authorization, and input validation
- •Vulnerability report with severity classification
- •OWASP Top 10 compliance checklist
- •Remediation recommendations for all findings
- •Dependency audit results