---
name: OWASP Security Testing
description: Security testing skill based on OWASP Top 10, covering ZAP scanning, security headers, input validation, authentication, and authorization testing.
version: 1.0.0
author: thetestingacademy
license: MIT
tags: [owasp, security, zap, penetration-testing, vulnerability, web-security]
testingTypes: [security]
frameworks: []
languages: [typescript, python]
domains: [web, api]
agents: [claude-code, cursor, github-copilot, windsurf, codex, aider, continue, cline, zed, bolt]
---
# OWASP Security Testing Skill
You are an expert security tester specializing in OWASP methodologies and web application security. When the user asks you to write, review, or plan security tests, follow these detailed instructions.
## Core Principles
1. **Defense in depth** -- Test every layer: input validation, authentication, authorization, encryption.
2. **OWASP Top 10 coverage** -- Systematically verify protection against the most common vulnerabilities.
3. **Automated + manual** -- Automated scans catch low-hanging fruit; manual testing catches logic flaws.
4. **Least privilege** -- Test that every endpoint enforces minimum required permissions.
5. **Secure defaults** -- Verify that default configurations are secure out of the box.
## OWASP Top 10 (2021) Testing Checklist
### A01: Broken Access Control
Test that users cannot access resources or perform actions beyond their permissions.
```typescript
import { test, expect } from '@playwright/test';
test.describe('Access Control Tests', () => {
test('regular user cannot access admin endpoints', async ({ request }) => {
// Login as regular user
const loginRes = await request.post('/api/auth/login', {
data: { email: 'user@example.com', password: 'UserPass123!' },
});
const { token } = await loginRes.json();
// Attempt to access admin-only endpoint
const adminRes = await request.get('/api/admin/users', {
headers: { Authorization: `Bearer ${token}` },
});
expect(adminRes.status()).toBe(403);
});
test('user cannot access other users data via IDOR', async ({ request }) => {
const loginRes = await request.post('/api/auth/login', {
data: { email: 'user1@example.com', password: 'UserPass123!' },
});
const { token } = await loginRes.json();
// Try to access another user's profile (IDOR)
const otherUserRes = await request.get('/api/users/other-user-id', {
headers: { Authorization: `Bearer ${token}` },
});
expect(otherUserRes.status()).toBe(403);
});
test('user cannot elevate privileges via API', async ({ request }) => {
const loginRes = await request.post('/api/auth/login', {
data: { email: 'user@example.com', password: 'UserPass123!' },
});
const { token } = await loginRes.json();
// Try to change own role to admin
const updateRes = await request.patch('/api/users/me', {
headers: { Authorization: `Bearer ${token}` },
data: { role: 'admin' },
});
// Should either reject or ignore the role field
if (updateRes.status() === 200) {
const body = await updateRes.json();
expect(body.role).not.toBe('admin');
}
});
test('cannot bypass authorization by manipulating request path', async ({ request }) => {
const paths = [
'/api/admin/users',
'/api/Admin/users',
'/api/ADMIN/users',
'/api/admin/./users',
'/api/admin/../admin/users',
'/api/admin%2Fusers',
];
for (const path of paths) {
const res = await request.get(path);
expect(res.status()).not.toBe(200);
}
});
});
```
### A02: Cryptographic Failures
```typescript
test.describe('Cryptographic Tests', () => {
test('API uses HTTPS only', async ({ request }) => {
const response = await request.get('/', {
headers: { Accept: 'text/html' },
});
const url = response.url();
expect(url).toMatch(/^https:\/\//);
});
test('sensitive data is not in URL parameters', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Password').fill('SecurePass123!');
await page.getByRole('button', { name: 'Sign in' }).click();
// Password should never appear in URL
const url = page.url();
expect(url).not.toContain('password');
expect(url).not.toContain('SecurePass123');
});
test('passwords are not returned in API responses', async ({ request }) => {
const loginRes = await request.post('/api/auth/login', {
data: { email: 'user@example.com', password: 'UserPass123!' },
});
const body = await loginRes.json();
const bodyStr = JSON.stringify(body);
expect(bodyStr).not.toContain('UserPass123!');
expect(body.user?.password).toBeUndefined();
expect(body.user?.passwordHash).toBeUndefined();
});
test('cookies have Secure flag', async ({ page }) => {
await page.goto('/');
const cookies = await page.context().cookies();
for (const cookie of cookies) {
if (cookie.name.includes('session') || cookie.name.includes('token')) {
expect(cookie.secure).toBe(true);
}
}
});
});
```
### A03: Injection
```typescript
test.describe('Injection Tests', () => {
const sqlInjectionPayloads = [
"' OR '1'='1",
"'; DROP TABLE users; --",
"1' UNION SELECT null, username, password FROM users --",
"admin'--",
"1; UPDATE users SET role='admin' WHERE email='attacker@evil.com'",
];
const xssPayloads = [
'',
'
',
'">',
"javascript:alert('XSS')",
'