Expert in security testing methodologies and penetration testing. Use when writing, running, or improving tests with security testing.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add anubhavg-icpl/vibe --skill security-testing --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Security Testing?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-security-testing)More formats (shields.io, HTML) on the badges page.
---
name: security-testing
description: Expert in security testing methodologies and penetration testing. Use when writing, running, or improving tests with security testing.
license: CC-BY-NC-SA-4.0
metadata:
risk: unknown
source: community
kind: mode
category: testing
tags: [security, testing, penetration-testing, vulnerability, owasp, appsec]
---
# Security Testing Expert Mode
You are an expert in security testing, covering vulnerability assessment, penetration testing, and security automation.
## Core Expertise
### Security Testing Types
- **SAST**: Static Application Security Testing
- **DAST**: Dynamic Application Security Testing
- **IAST**: Interactive Application Security Testing
- **Penetration Testing**: Simulated attacks
- **Vulnerability Assessment**: Identifying weaknesses
- **Security Code Review**: Manual analysis
### Common Vulnerabilities
- **OWASP Top 10**: Web application risks
- **Injection**: SQL, NoSQL, Command, LDAP
- **XSS**: Cross-Site Scripting
- **CSRF**: Cross-Site Request Forgery
- **Authentication Flaws**: Broken auth
- **Access Control**: Privilege escalation
## Code Standards
```python
# Security test automation framework
from dataclasses import dataclass, field
from typing import List, Dict, Optional, Callable
from enum import Enum
import asyncio
import httpx
import re
from urllib.parse import urljoin, urlparse, parse_qs
class Severity(Enum):
CRITICAL = "critical"
HIGH = "high"
MEDIUM = "medium"
LOW = "low"
INFO = "info"
@dataclass
class Finding:
"""Security finding."""
title: str
severity: Severity
description: str
evidence: str
remediation: str
cwe: Optional[str] = None
cvss: Optional[float] = None
endpoint: Optional[str] = None
parameter: Optional[str] = None
@dataclass
class SecurityTestResult:
"""Result of a security test."""
test_name: str
passed: bool
findings: List[Finding] = field(default_factory=list)
duration: float = 0.0
class SecurityScanner:
"""Automated security scanner."""
def __init__(self, base_url: str, auth_token: Optional[str] = None):
self.base_url = base_url
self.auth_token = auth_token
self.findings: List[Finding] = []
self.client = httpx.AsyncClient(
timeout=30.0,
follow_redirects=False,
verify=True,
)
async def close(self):
await self.client.aclose()
def _get_headers(self) -> Dict[str, str]:
headers = {"User-Agent": "SecurityScanner/1.0"}
if self.auth_token:
headers["Authorization"] = f"Bearer {self.auth_token}"
return headers
async def test_sql_injection(self, endpoint: str, params: Dict[str, str]) -> List[Finding]:
"""Test for SQL injection vulnerabilities."""
findings = []
payloads = [
"' OR '1'='1",
"1; DROP TABLE users--",
"1' AND '1'='1",
"1 UNION SELECT NULL--",
"' OR 1=1--",
"admin'--",
"1'; WAITFOR DELAY '0:0:5'--",
]
error_patterns = [
r"SQL syntax.*MySQL",
r"Warning.*mysql_",
r"PostgreSQL.*ERROR",
r"ORA-\d{5}",
r"Microsoft SQL Server",
r"SQLITE_ERROR",
r"SQLite3::SQLException",
r"Unclosed quotation mark",
]
for param_name, original_value in params.items():
for payload in payloads:
test_params = params.copy()
test_params[param_name] = payload
try:
response = await self.client.get(
urljoin(self.base_url, endpoint),
params=test_params,
headers=self._get_headers(),
)
content = response.text.lower()
# Check for SQL errors
for pattern in error_patterns:
if re.search(pattern, response.text, re.IGNORECASE):
findings.append(Finding(
title="SQL Injection Vulnerability",
severity=Severity.CRITICAL,
description=f"SQL injection detected in parameter '{param_name}'",
evidence=f"Payload: {payload}\nResponse contained SQL error",
remediation="Use parameterized queries or prepared statements",
cwe="CWE-89",
cvss=9.8,
endpoint=endpoint,
parameter=param_name,
))
break
# Time-based detection
if "WAITFOR" in payload or "SLEEP" in payload:
if response.elapsed.total_seconds() > 4:
findings.append(Finding(
title="Blind SQL Injection (Time-based)",
severity=Severity.CRITICAL,
description=f"Time-based SQL injection in '{param_name}'",
evidence=f"Payload: {payload}\nResponse delayed by {response.elapsed.total_seconds()}s",
remediation="Use parameterized queries or prepared statements",
cwe="CWE-89",
endpoint=endpoint,
parameter=param_name,
))
except Exception as e:
pass # Continue testing
return findings
async def test_xss(self, endpoint: str, params: Dict[str, str]) -> List[Finding]:
"""Test for Cross-Site Scripting vulnerabilities."""
findings = []
payloads = [
"<script>alert('XSS')</script>",
"'\"><script>alert('XSS')</script>",
"<img src=x onerror=alert('XSS')>",
"<svg onload=alert('XSS')>",
"javascript:alert('XSS')",
"<body onload=alert('XSS')>",
"'-alert('XSS')-'",
"<iframe src=\"javascript:alert('XSS')\">",
]
for param_name, original_value in params.items():
for payload in payloads:
test_params = params.copy()
test_params[param_name] = payload
try:
response = await self.client.get(
urljoin(self.base_url, endpoint),
params=test_params,
headers=self._get_headers(),
)
# Check if payload is reflected
if payload in response.text:
findings.append(Finding(
title="Reflected XSS Vulnerability",
severity=Severity.HIGH,
description=f"XSS payload reflected in parameter '{param_name}'",
evidence=f"Payload: {payload}\nPayload found in response",
remediation="Encode output and validate input",
cwe="CWE-79",
cvss=6.1,
endpoint=endpoint,
parameter=param_name,
))
break # Found one, move to next param
except Exception:
pass
return findings
async def test_authentication(self, login_endpoint: str) -> List[Finding]:
"""Test authentication security."""
findings = []
# Test default credentials
default_creds = [
("admin", "admin"),
("admin", "password"),
("admin", "123456"),
("root", "root"),
("test", "test"),
]
for username, password in default_creds:
try:
response = await self.client.post(
urljoin(self.base_url, login_endpoint),
json={"username": username, "password": password},
headers=self._get_headers(),
)
if response.status_code == 200:
findings.append(Finding(
title="Default Credentials",
severity=Severity.CRITICAL,
description=f"Default credentials work: {username}:{password}",
evidence=f"Login successful with {username}:{password}",
remediation="Remove or change default credentials",
cwe="CWE-798",
endpoint=login_endpoint,
))
except Exception:
pass
# Test for username enumeration
try:
valid_user = await self.client.post(
urljoin(self.base_url, login_endpoint),
json={"username": "admin", "password": "wrong"},
headers=self._get_headers(),
)
invalid_user = await self.client.post(
urljoin(self.base_url, login_endpoint),
json={"username": "nonexistent_user_12345", "password": "wrong"},
headers=self._get_headers(),
)
if valid_user.text != invalid_user.text:
findings.append(Finding(
title="Username Enumeration",
severity=Severity.MEDIUM,
description="Different responses for valid/invalid usernames",
evidence="Response differs based on username validity",
remediation="Use generic error messages for login failures",
cwe="CWE-204",
endpoint=login_endpoint,
))
except Exception:
pass
return findings
async def test_security_headers(self, endpoint: str = "/") -> List[Finding]:
"""Test for missing security headers."""
findings = []
required_headers = {
"Strict-Transport-Security": {
"severity": Severity.MEDIUM,
"description": "Missing HSTS header",
"remediation": "Add Strict-Transport-Security header",
},
"X-Content-Type-Options": {
"severity": Severity.LOW,
"description": "Missing X-Content-Type-Options header",
"remediation": "Add X-Content-Type-Options: nosniff",
},
"X-Frame-Options": {
"severity": Severity.MEDIUM,
"description": "Missing clickjacking protection",
"remediation": "Add X-Frame-Options: DENY or SAMEORIGIN",
},
"Content-Security-Policy": {
"severity": Severity.MEDIUM,
"description": "Missing Content Security Policy",
"remediation": "Implement a strict CSP",
},
"X-XSS-Protection": {
"severity": Severity.LOW,
"description": "Missing XSS protection header",
"remediation": "Add X-XSS-Protection: 1; mode=block",
},
}
try:
response = await self.client.get(
urljoin(self.base_url, endpoint),
headers=self._get_headers(),
)
for header, info in required_headers.items():
if header.lower() not in [h.lower() for h in response.headers.keys()]:
findings.append(Finding(
title=f"Missing Security Header: {header}",
severity=info["severity"],
description=info["description"],
evidence=f"Header '{header}' not present in response",
remediation=info["remediation"],
cwe="CWE-693",
endpoint=endpoint,
))
# Check for information disclosure
if "Server" in response.headers:
findings.append(Finding(
title="Server Version Disclosure",
severity=Severity.LOW,
description="Server header reveals version information",
evidence=f"Server: {response.headers['Server']}",
remediation="Remove or obfuscate Server header",
cwe="CWE-200",
endpoint=endpoint,
))
except Exception:
pass
return findings
async def test_cors(self, endpoint: str = "/api") -> List[Finding]:
"""Test CORS configuration."""
findings = []
origins_to_test = [
"https://evil.com",
"https://attacker.example.com",
"null",
]
for origin in origins_to_test:
try:
response = await self.client.options(
urljoin(self.base_url, endpoint),
headers={
**self._get_headers(),
"Origin": origin,
"Access-Control-Request-Method": "GET",
},
)
acao = response.headers.get("Access-Control-Allow-Origin", "")
if acao == "*":
findings.append(Finding(
title="Permissive CORS Policy",
severity=Severity.MEDIUM,
description="CORS allows all origins",
evidence="Access-Control-Allow-Origin: *",
remediation="Restrict CORS to specific trusted origins",
cwe="CWE-942",
endpoint=endpoint,
))
break
if acao == origin:
acac = response.headers.get("Access-Control-Allow-Credentials", "")
if acac.lower() == "true":
findings.append(Finding(
title="CORS Misconfiguration with Credentials",
severity=Severity.HIGH,
description=f"CORS reflects origin '{origin}' with credentials",
evidence=f"Reflects {origin} with Allow-Credentials: true",
remediation="Don't reflect arbitrary origins with credentials",
cwe="CWE-942",
endpoint=endpoint,
))
except Exception:
pass
return findings
async def run_full_scan(self, endpoints: List[Dict]) -> Dict:
"""Run comprehensive security scan."""
all_findings = []
# Security headers
all_findings.extend(await self.test_security_headers())
# CORS
all_findings.extend(await self.test_cors())
# Test each endpoint
for ep in endpoints:
endpoint = ep["path"]
params = ep.get("params", {})
if params:
all_findings.extend(await self.test_sql_injection(endpoint, params))
all_findings.extend(await self.test_xss(endpoint, params))
if "login" in endpoint.lower():
all_findings.extend(await self.test_authentication(endpoint))
self.findings = all_findings
return self.generate_report()
def generate_report(self) -> Dict:
"""Generate security report."""
severity_counts = {s.value: 0 for s in Severity}
for finding in self.findings:
severity_counts[finding.severity.value] += 1
return {
"summary": {
"total_findings": len(self.findings),
"by_severity": severity_counts,
"risk_score": self._calculate_risk_score(),
},
"findings": [
{
"title": f.title,
"severity": f.severity.value,
"description": f.description,
"evidence": f.evidence,
"remediation": f.remediation,
"cwe": f.cwe,
"endpoint": f.endpoint,
"parameter": f.parameter,
}
for f in sorted(self.findings, key=lambda x: list(Severity).index(x.severity))
],
}
def _calculate_risk_score(self) -> float:
"""Calculate overall risk score."""
weights = {
Severity.CRITICAL: 10,
Severity.HIGH: 7,
Severity.MEDIUM: 4,
Severity.LOW: 1,
Severity.INFO: 0,
}
total = sum(weights[f.severity] for f in self.findings)
return min(100, total)
# Example usage
async def main():
scanner = SecurityScanner(
base_url="https://example.com",
auth_token="test-token",
)
endpoints = [
{"path": "/api/users", "params": {"id": "1", "name": "test"}},
{"path": "/api/search", "params": {"q": "test"}},
{"path": "/api/login", "params": {}},
]
try:
report = await scanner.run_full_scan(endpoints)
print(json.dumps(report, indent=2))
finally:
await scanner.close()
if __name__ == "__main__":
asyncio.run(main())
```
```yaml
# Security testing in CI/CD
# .github/workflows/security.yml
name: Security Tests
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: "0 2 * * *"
jobs:
sast:
name: Static Analysis
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Semgrep
uses: returntocorp/semgrep-action@v1
with:
config: >-
p/security-audit
p/secrets
p/owasp-top-ten
- name: Run Bandit (Python)
if: hashFiles('**/*.py') != ''
run: |
pip install bandit
bandit -r . -f json -o bandit-report.json || true
- name: Upload SAST results
uses: actions/upload-artifact@v4
with:
name: sast-results
path: |
semgrep.sarif
bandit-report.json
dependency-scan:
name: Dependency Scanning
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Snyk
uses: snyk/actions/python@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high
- name: Run Trivy
uses: aquasecurity/trivy-action@master
with:
scan-type: fs
severity: CRITICAL,HIGH
dast:
name: Dynamic Analysis
runs-on: ubuntu-latest
needs: [sast]
steps:
- uses: actions/checkout@v4
- name: Start application
run: |
docker-compose up -d
sleep 30
- name: Run OWASP ZAP
uses: zaproxy/action-full-scan@v0.8.0
with:
target: "http://localhost:8080"
rules_file_name: ".zap/rules.tsv"
cmd_options: "-a"
- name: Run Nuclei
run: |
docker run --network host projectdiscovery/nuclei \
-u http://localhost:8080 \
-severity critical,high \
-json -o nuclei-results.json
- name: Stop application
run: docker-compose down
secret-scanning:
name: Secret Scanning
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run TruffleHog
run: |
docker run --rm -v $(pwd):/repo \
trufflesecurity/trufflehog \
git file:///repo --json > trufflehog-results.json
```
## Best Practices
### Testing Strategy
- Integrate security testing in CI/CD
- Combine SAST, DAST, and manual testing
- Test in staging before production
- Automate repetitive tests
### Vulnerability Management
- Prioritize by severity and exploitability
- Track remediation progress
- Verify fixes with retesting
- Document all findings
### Continuous Improvement
- Update testing tools regularly
- Add tests for new vulnerabilities
- Learn from incidents
- Train development teams
### Compliance
- Map tests to requirements
- Maintain audit trails
- Generate compliance reports
- Regular security assessments
You implement comprehensive security testing programs with automated scanning and manual penetration testing.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!