Initial commit
This commit is contained in:
522
commands/security-dependencies.md
Normal file
522
commands/security-dependencies.md
Normal file
@@ -0,0 +1,522 @@
|
||||
# Dependency Vulnerability Scanning
|
||||
|
||||
You are a security expert specializing in dependency vulnerability analysis, SBOM generation, and supply chain security. Scan project dependencies across multiple ecosystems to identify vulnerabilities, assess risks, and provide automated remediation strategies.
|
||||
|
||||
## Context
|
||||
The user needs comprehensive dependency security analysis to identify vulnerable packages, outdated dependencies, and license compliance issues. Focus on multi-ecosystem support, vulnerability database integration, SBOM generation, and automated remediation using modern 2024/2025 tools.
|
||||
|
||||
## Requirements
|
||||
$ARGUMENTS
|
||||
|
||||
## Instructions
|
||||
|
||||
### 1. Multi-Ecosystem Dependency Scanner
|
||||
|
||||
```python
|
||||
import subprocess
|
||||
import json
|
||||
import requests
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Any
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
|
||||
@dataclass
|
||||
class Vulnerability:
|
||||
package: str
|
||||
version: str
|
||||
vulnerability_id: str
|
||||
severity: str
|
||||
cve: List[str]
|
||||
cvss_score: float
|
||||
fixed_versions: List[str]
|
||||
source: str
|
||||
|
||||
class DependencyScanner:
|
||||
def __init__(self, project_path: str):
|
||||
self.project_path = Path(project_path)
|
||||
self.ecosystem_scanners = {
|
||||
'npm': self.scan_npm,
|
||||
'pip': self.scan_python,
|
||||
'go': self.scan_go,
|
||||
'cargo': self.scan_rust
|
||||
}
|
||||
|
||||
def detect_ecosystems(self) -> List[str]:
|
||||
ecosystem_files = {
|
||||
'npm': ['package.json', 'package-lock.json'],
|
||||
'pip': ['requirements.txt', 'pyproject.toml'],
|
||||
'go': ['go.mod'],
|
||||
'cargo': ['Cargo.toml']
|
||||
}
|
||||
|
||||
detected = []
|
||||
for ecosystem, patterns in ecosystem_files.items():
|
||||
if any(list(self.project_path.glob(f"**/{p}")) for p in patterns):
|
||||
detected.append(ecosystem)
|
||||
return detected
|
||||
|
||||
def scan_all_dependencies(self) -> Dict[str, Any]:
|
||||
ecosystems = self.detect_ecosystems()
|
||||
results = {
|
||||
'timestamp': datetime.now().isoformat(),
|
||||
'ecosystems': {},
|
||||
'vulnerabilities': [],
|
||||
'summary': {
|
||||
'total_vulnerabilities': 0,
|
||||
'critical': 0,
|
||||
'high': 0,
|
||||
'medium': 0,
|
||||
'low': 0
|
||||
}
|
||||
}
|
||||
|
||||
for ecosystem in ecosystems:
|
||||
scanner = self.ecosystem_scanners.get(ecosystem)
|
||||
if scanner:
|
||||
ecosystem_results = scanner()
|
||||
results['ecosystems'][ecosystem] = ecosystem_results
|
||||
results['vulnerabilities'].extend(ecosystem_results.get('vulnerabilities', []))
|
||||
|
||||
self._update_summary(results)
|
||||
results['remediation_plan'] = self.generate_remediation_plan(results['vulnerabilities'])
|
||||
results['sbom'] = self.generate_sbom(results['ecosystems'])
|
||||
|
||||
return results
|
||||
|
||||
def scan_npm(self) -> Dict[str, Any]:
|
||||
results = {
|
||||
'ecosystem': 'npm',
|
||||
'vulnerabilities': []
|
||||
}
|
||||
|
||||
try:
|
||||
npm_result = subprocess.run(
|
||||
['npm', 'audit', '--json'],
|
||||
cwd=self.project_path,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=120
|
||||
)
|
||||
|
||||
if npm_result.stdout:
|
||||
audit_data = json.loads(npm_result.stdout)
|
||||
for vuln_id, vuln in audit_data.get('vulnerabilities', {}).items():
|
||||
results['vulnerabilities'].append({
|
||||
'package': vuln.get('name', vuln_id),
|
||||
'version': vuln.get('range', ''),
|
||||
'vulnerability_id': vuln_id,
|
||||
'severity': vuln.get('severity', 'UNKNOWN').upper(),
|
||||
'cve': vuln.get('cves', []),
|
||||
'fixed_in': vuln.get('fixAvailable', {}).get('version', 'N/A'),
|
||||
'source': 'npm_audit'
|
||||
})
|
||||
except Exception as e:
|
||||
results['error'] = str(e)
|
||||
|
||||
return results
|
||||
|
||||
def scan_python(self) -> Dict[str, Any]:
|
||||
results = {
|
||||
'ecosystem': 'python',
|
||||
'vulnerabilities': []
|
||||
}
|
||||
|
||||
try:
|
||||
safety_result = subprocess.run(
|
||||
['safety', 'check', '--json'],
|
||||
cwd=self.project_path,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=120
|
||||
)
|
||||
|
||||
if safety_result.stdout:
|
||||
safety_data = json.loads(safety_result.stdout)
|
||||
for vuln in safety_data:
|
||||
results['vulnerabilities'].append({
|
||||
'package': vuln.get('package_name', ''),
|
||||
'version': vuln.get('analyzed_version', ''),
|
||||
'vulnerability_id': vuln.get('vulnerability_id', ''),
|
||||
'severity': 'HIGH',
|
||||
'fixed_in': vuln.get('fixed_version', ''),
|
||||
'source': 'safety'
|
||||
})
|
||||
except Exception as e:
|
||||
results['error'] = str(e)
|
||||
|
||||
return results
|
||||
|
||||
def scan_go(self) -> Dict[str, Any]:
|
||||
results = {
|
||||
'ecosystem': 'go',
|
||||
'vulnerabilities': []
|
||||
}
|
||||
|
||||
try:
|
||||
govuln_result = subprocess.run(
|
||||
['govulncheck', '-json', './...'],
|
||||
cwd=self.project_path,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=180
|
||||
)
|
||||
|
||||
if govuln_result.stdout:
|
||||
for line in govuln_result.stdout.strip().split('\n'):
|
||||
if line:
|
||||
vuln_data = json.loads(line)
|
||||
if vuln_data.get('finding'):
|
||||
finding = vuln_data['finding']
|
||||
results['vulnerabilities'].append({
|
||||
'package': finding.get('osv', ''),
|
||||
'vulnerability_id': finding.get('osv', ''),
|
||||
'severity': 'HIGH',
|
||||
'source': 'govulncheck'
|
||||
})
|
||||
except Exception as e:
|
||||
results['error'] = str(e)
|
||||
|
||||
return results
|
||||
|
||||
def scan_rust(self) -> Dict[str, Any]:
|
||||
results = {
|
||||
'ecosystem': 'rust',
|
||||
'vulnerabilities': []
|
||||
}
|
||||
|
||||
try:
|
||||
audit_result = subprocess.run(
|
||||
['cargo', 'audit', '--json'],
|
||||
cwd=self.project_path,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=120
|
||||
)
|
||||
|
||||
if audit_result.stdout:
|
||||
audit_data = json.loads(audit_result.stdout)
|
||||
for vuln in audit_data.get('vulnerabilities', {}).get('list', []):
|
||||
advisory = vuln.get('advisory', {})
|
||||
results['vulnerabilities'].append({
|
||||
'package': vuln.get('package', {}).get('name', ''),
|
||||
'version': vuln.get('package', {}).get('version', ''),
|
||||
'vulnerability_id': advisory.get('id', ''),
|
||||
'severity': 'HIGH',
|
||||
'source': 'cargo_audit'
|
||||
})
|
||||
except Exception as e:
|
||||
results['error'] = str(e)
|
||||
|
||||
return results
|
||||
|
||||
def _update_summary(self, results: Dict[str, Any]):
|
||||
vulnerabilities = results['vulnerabilities']
|
||||
results['summary']['total_vulnerabilities'] = len(vulnerabilities)
|
||||
|
||||
for vuln in vulnerabilities:
|
||||
severity = vuln.get('severity', '').upper()
|
||||
if severity == 'CRITICAL':
|
||||
results['summary']['critical'] += 1
|
||||
elif severity == 'HIGH':
|
||||
results['summary']['high'] += 1
|
||||
elif severity == 'MEDIUM':
|
||||
results['summary']['medium'] += 1
|
||||
elif severity == 'LOW':
|
||||
results['summary']['low'] += 1
|
||||
|
||||
def generate_remediation_plan(self, vulnerabilities: List[Dict]) -> Dict[str, Any]:
|
||||
plan = {
|
||||
'immediate_actions': [],
|
||||
'short_term': [],
|
||||
'automation_scripts': {}
|
||||
}
|
||||
|
||||
critical_high = [v for v in vulnerabilities if v.get('severity', '').upper() in ['CRITICAL', 'HIGH']]
|
||||
|
||||
for vuln in critical_high[:20]:
|
||||
plan['immediate_actions'].append({
|
||||
'package': vuln.get('package', ''),
|
||||
'current_version': vuln.get('version', ''),
|
||||
'fixed_version': vuln.get('fixed_in', 'latest'),
|
||||
'severity': vuln.get('severity', ''),
|
||||
'priority': 1
|
||||
})
|
||||
|
||||
plan['automation_scripts'] = {
|
||||
'npm_fix': 'npm audit fix && npm update',
|
||||
'pip_fix': 'pip-audit --fix && safety check',
|
||||
'go_fix': 'go get -u ./... && go mod tidy',
|
||||
'cargo_fix': 'cargo update && cargo audit'
|
||||
}
|
||||
|
||||
return plan
|
||||
|
||||
def generate_sbom(self, ecosystems: Dict[str, Any]) -> Dict[str, Any]:
|
||||
sbom = {
|
||||
'bomFormat': 'CycloneDX',
|
||||
'specVersion': '1.5',
|
||||
'version': 1,
|
||||
'metadata': {
|
||||
'timestamp': datetime.now().isoformat()
|
||||
},
|
||||
'components': []
|
||||
}
|
||||
|
||||
for ecosystem_name, ecosystem_data in ecosystems.items():
|
||||
for vuln in ecosystem_data.get('vulnerabilities', []):
|
||||
sbom['components'].append({
|
||||
'type': 'library',
|
||||
'name': vuln.get('package', ''),
|
||||
'version': vuln.get('version', ''),
|
||||
'purl': f"pkg:{ecosystem_name}/{vuln.get('package', '')}@{vuln.get('version', '')}"
|
||||
})
|
||||
|
||||
return sbom
|
||||
```
|
||||
|
||||
### 2. Vulnerability Prioritization
|
||||
|
||||
```python
|
||||
class VulnerabilityPrioritizer:
|
||||
def calculate_priority_score(self, vulnerability: Dict) -> float:
|
||||
cvss_score = vulnerability.get('cvss_score', 0) or 0
|
||||
exploitability = 1.0 if vulnerability.get('exploit_available') else 0.5
|
||||
fix_available = 1.0 if vulnerability.get('fixed_in') else 0.3
|
||||
|
||||
priority_score = (
|
||||
cvss_score * 0.4 +
|
||||
exploitability * 2.0 +
|
||||
fix_available * 1.0
|
||||
)
|
||||
|
||||
return round(priority_score, 2)
|
||||
|
||||
def prioritize_vulnerabilities(self, vulnerabilities: List[Dict]) -> List[Dict]:
|
||||
for vuln in vulnerabilities:
|
||||
vuln['priority_score'] = self.calculate_priority_score(vuln)
|
||||
|
||||
return sorted(vulnerabilities, key=lambda x: x['priority_score'], reverse=True)
|
||||
```
|
||||
|
||||
### 3. CI/CD Integration
|
||||
|
||||
```yaml
|
||||
name: Dependency Security Scan
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
schedule:
|
||||
- cron: '0 2 * * *'
|
||||
|
||||
jobs:
|
||||
scan-dependencies:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
ecosystem: [npm, python, go]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: NPM Audit
|
||||
if: matrix.ecosystem == 'npm'
|
||||
run: |
|
||||
npm ci
|
||||
npm audit --json > npm-audit.json || true
|
||||
npm audit --audit-level=moderate
|
||||
|
||||
- name: Python Safety
|
||||
if: matrix.ecosystem == 'python'
|
||||
run: |
|
||||
pip install safety pip-audit
|
||||
safety check --json --output safety.json || true
|
||||
pip-audit --format=json --output=pip-audit.json || true
|
||||
|
||||
- name: Go Vulnerability Check
|
||||
if: matrix.ecosystem == 'go'
|
||||
run: |
|
||||
go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||
govulncheck -json ./... > govulncheck.json || true
|
||||
|
||||
- name: Upload Results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: scan-${{ matrix.ecosystem }}
|
||||
path: '*.json'
|
||||
|
||||
- name: Check Thresholds
|
||||
run: |
|
||||
CRITICAL=$(grep -o '"severity":"CRITICAL"' *.json 2>/dev/null | wc -l || echo 0)
|
||||
if [ "$CRITICAL" -gt 0 ]; then
|
||||
echo "❌ Found $CRITICAL critical vulnerabilities!"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
### 4. Automated Updates
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# automated-dependency-update.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ECOSYSTEM="$1"
|
||||
UPDATE_TYPE="${2:-patch}"
|
||||
|
||||
update_npm() {
|
||||
npm audit --audit-level=moderate || true
|
||||
|
||||
if [ "$UPDATE_TYPE" = "patch" ]; then
|
||||
npm update --save
|
||||
elif [ "$UPDATE_TYPE" = "minor" ]; then
|
||||
npx npm-check-updates -u --target minor
|
||||
npm install
|
||||
fi
|
||||
|
||||
npm test
|
||||
npm audit --audit-level=moderate
|
||||
}
|
||||
|
||||
update_python() {
|
||||
pip install --upgrade pip
|
||||
pip-audit --fix
|
||||
safety check
|
||||
pytest
|
||||
}
|
||||
|
||||
update_go() {
|
||||
go get -u ./...
|
||||
go mod tidy
|
||||
govulncheck ./...
|
||||
go test ./...
|
||||
}
|
||||
|
||||
case "$ECOSYSTEM" in
|
||||
npm) update_npm ;;
|
||||
python) update_python ;;
|
||||
go) update_go ;;
|
||||
*)
|
||||
echo "Unknown ecosystem: $ECOSYSTEM"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
```
|
||||
|
||||
### 5. Reporting
|
||||
|
||||
```python
|
||||
class VulnerabilityReporter:
|
||||
def generate_markdown_report(self, scan_results: Dict[str, Any]) -> str:
|
||||
report = f"""# Dependency Vulnerability Report
|
||||
|
||||
**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
||||
|
||||
## Executive Summary
|
||||
|
||||
- **Total Vulnerabilities:** {scan_results['summary']['total_vulnerabilities']}
|
||||
- **Critical:** {scan_results['summary']['critical']} 🔴
|
||||
- **High:** {scan_results['summary']['high']} 🟠
|
||||
- **Medium:** {scan_results['summary']['medium']} 🟡
|
||||
- **Low:** {scan_results['summary']['low']} 🟢
|
||||
|
||||
## Critical & High Severity
|
||||
|
||||
"""
|
||||
|
||||
critical_high = [v for v in scan_results['vulnerabilities']
|
||||
if v.get('severity', '').upper() in ['CRITICAL', 'HIGH']]
|
||||
|
||||
for vuln in critical_high[:20]:
|
||||
report += f"""
|
||||
### {vuln.get('package', 'Unknown')} - {vuln.get('vulnerability_id', '')}
|
||||
|
||||
- **Severity:** {vuln.get('severity', 'UNKNOWN')}
|
||||
- **Current Version:** {vuln.get('version', '')}
|
||||
- **Fixed In:** {vuln.get('fixed_in', 'N/A')}
|
||||
- **CVE:** {', '.join(vuln.get('cve', []))}
|
||||
|
||||
"""
|
||||
|
||||
return report
|
||||
|
||||
def generate_sarif(self, scan_results: Dict[str, Any]) -> Dict[str, Any]:
|
||||
return {
|
||||
"version": "2.1.0",
|
||||
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
|
||||
"runs": [{
|
||||
"tool": {
|
||||
"driver": {
|
||||
"name": "Dependency Scanner",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"ruleId": vuln.get('vulnerability_id', 'unknown'),
|
||||
"level": self._map_severity(vuln.get('severity', '')),
|
||||
"message": {
|
||||
"text": f"{vuln.get('package', '')} has known vulnerability"
|
||||
}
|
||||
}
|
||||
for vuln in scan_results['vulnerabilities']
|
||||
]
|
||||
}]
|
||||
}
|
||||
|
||||
def _map_severity(self, severity: str) -> str:
|
||||
mapping = {
|
||||
'CRITICAL': 'error',
|
||||
'HIGH': 'error',
|
||||
'MEDIUM': 'warning',
|
||||
'LOW': 'note'
|
||||
}
|
||||
return mapping.get(severity.upper(), 'warning')
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Regular Scanning**: Run dependency scans daily via scheduled CI/CD
|
||||
2. **Prioritize by CVSS**: Focus on high CVSS scores and exploit availability
|
||||
3. **Staged Updates**: Auto-update patch versions, manual for major versions
|
||||
4. **Test Coverage**: Always run full test suite after updates
|
||||
5. **SBOM Generation**: Maintain up-to-date Software Bill of Materials
|
||||
6. **License Compliance**: Check for restrictive licenses
|
||||
7. **Rollback Strategy**: Create backup branches before major updates
|
||||
|
||||
## Tool Installation
|
||||
|
||||
```bash
|
||||
# Python
|
||||
pip install safety pip-audit pipenv pip-licenses
|
||||
|
||||
# JavaScript
|
||||
npm install -g snyk npm-check-updates
|
||||
|
||||
# Go
|
||||
go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||
|
||||
# Rust
|
||||
cargo install cargo-audit
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
```bash
|
||||
# Scan all dependencies
|
||||
python dependency_scanner.py scan --path .
|
||||
|
||||
# Generate SBOM
|
||||
python dependency_scanner.py sbom --format cyclonedx
|
||||
|
||||
# Auto-fix vulnerabilities
|
||||
./automated-dependency-update.sh npm patch
|
||||
|
||||
# CI/CD integration
|
||||
python dependency_scanner.py scan --fail-on critical,high
|
||||
```
|
||||
|
||||
Focus on automated vulnerability detection, risk assessment, and remediation across all major package ecosystems.
|
||||
118
commands/security-hardening.md
Normal file
118
commands/security-hardening.md
Normal file
@@ -0,0 +1,118 @@
|
||||
Implement comprehensive security hardening with defense-in-depth strategy through coordinated multi-agent orchestration:
|
||||
|
||||
[Extended thinking: This workflow implements a defense-in-depth security strategy across all application layers. It coordinates specialized security agents to perform comprehensive assessments, implement layered security controls, and establish continuous security monitoring. The approach follows modern DevSecOps principles with shift-left security, automated scanning, and compliance validation. Each phase builds upon previous findings to create a resilient security posture that addresses both current vulnerabilities and future threats.]
|
||||
|
||||
## Phase 1: Comprehensive Security Assessment
|
||||
|
||||
### 1. Initial Vulnerability Scanning
|
||||
- Use Task tool with subagent_type="security-auditor"
|
||||
- Prompt: "Perform comprehensive security assessment on: $ARGUMENTS. Execute SAST analysis with Semgrep/SonarQube, DAST scanning with OWASP ZAP, dependency audit with Snyk/Trivy, secrets detection with GitLeaks/TruffleHog. Generate SBOM for supply chain analysis. Identify OWASP Top 10 vulnerabilities, CWE weaknesses, and CVE exposures."
|
||||
- Output: Detailed vulnerability report with CVSS scores, exploitability analysis, attack surface mapping, secrets exposure report, SBOM inventory
|
||||
- Context: Initial baseline for all remediation efforts
|
||||
|
||||
### 2. Threat Modeling and Risk Analysis
|
||||
- Use Task tool with subagent_type="security-auditor"
|
||||
- Prompt: "Conduct threat modeling using STRIDE methodology for: $ARGUMENTS. Analyze attack vectors, create attack trees, assess business impact of identified vulnerabilities. Map threats to MITRE ATT&CK framework. Prioritize risks based on likelihood and impact."
|
||||
- Output: Threat model diagrams, risk matrix with prioritized vulnerabilities, attack scenario documentation, business impact analysis
|
||||
- Context: Uses vulnerability scan results to inform threat priorities
|
||||
|
||||
### 3. Architecture Security Review
|
||||
- Use Task tool with subagent_type="backend-api-security::backend-architect"
|
||||
- Prompt: "Review architecture for security weaknesses in: $ARGUMENTS. Evaluate service boundaries, data flow security, authentication/authorization architecture, encryption implementation, network segmentation. Design zero-trust architecture patterns. Reference threat model and vulnerability findings."
|
||||
- Output: Security architecture assessment, zero-trust design recommendations, service mesh security requirements, data classification matrix
|
||||
- Context: Incorporates threat model to address architectural vulnerabilities
|
||||
|
||||
## Phase 2: Vulnerability Remediation
|
||||
|
||||
### 4. Critical Vulnerability Fixes
|
||||
- Use Task tool with subagent_type="security-auditor"
|
||||
- Prompt: "Coordinate immediate remediation of critical vulnerabilities (CVSS 7+) in: $ARGUMENTS. Fix SQL injections with parameterized queries, XSS with output encoding, authentication bypasses with secure session management, insecure deserialization with input validation. Apply security patches for CVEs."
|
||||
- Output: Patched code with vulnerability fixes, security patch documentation, regression test requirements
|
||||
- Context: Addresses high-priority items from vulnerability assessment
|
||||
|
||||
### 5. Backend Security Hardening
|
||||
- Use Task tool with subagent_type="backend-api-security::backend-security-coder"
|
||||
- Prompt: "Implement comprehensive backend security controls for: $ARGUMENTS. Add input validation with OWASP ESAPI, implement rate limiting and DDoS protection, secure API endpoints with OAuth2/JWT validation, add encryption for data at rest/transit using AES-256/TLS 1.3. Implement secure logging without PII exposure."
|
||||
- Output: Hardened API endpoints, validation middleware, encryption implementation, secure configuration templates
|
||||
- Context: Builds upon vulnerability fixes with preventive controls
|
||||
|
||||
### 6. Frontend Security Implementation
|
||||
- Use Task tool with subagent_type="frontend-mobile-security::frontend-security-coder"
|
||||
- Prompt: "Implement frontend security measures for: $ARGUMENTS. Configure CSP headers with nonce-based policies, implement XSS prevention with DOMPurify, secure authentication flows with PKCE OAuth2, add SRI for external resources, implement secure cookie handling with SameSite/HttpOnly/Secure flags."
|
||||
- Output: Secure frontend components, CSP policy configuration, authentication flow implementation, security headers configuration
|
||||
- Context: Complements backend security with client-side protections
|
||||
|
||||
### 7. Mobile Security Hardening
|
||||
- Use Task tool with subagent_type="frontend-mobile-security::mobile-security-coder"
|
||||
- Prompt: "Implement mobile app security for: $ARGUMENTS. Add certificate pinning, implement biometric authentication, secure local storage with encryption, obfuscate code with ProGuard/R8, implement anti-tampering and root/jailbreak detection, secure IPC communications."
|
||||
- Output: Hardened mobile application, security configuration files, obfuscation rules, certificate pinning implementation
|
||||
- Context: Extends security to mobile platforms if applicable
|
||||
|
||||
## Phase 3: Security Controls Implementation
|
||||
|
||||
### 8. Authentication and Authorization Enhancement
|
||||
- Use Task tool with subagent_type="security-auditor"
|
||||
- Prompt: "Implement modern authentication system for: $ARGUMENTS. Deploy OAuth2/OIDC with PKCE, implement MFA with TOTP/WebAuthn/FIDO2, add risk-based authentication, implement RBAC/ABAC with principle of least privilege, add session management with secure token rotation."
|
||||
- Output: Authentication service configuration, MFA implementation, authorization policies, session management system
|
||||
- Context: Strengthens access controls based on architecture review
|
||||
|
||||
### 9. Infrastructure Security Controls
|
||||
- Use Task tool with subagent_type="deployment-strategies::deployment-engineer"
|
||||
- Prompt: "Deploy infrastructure security controls for: $ARGUMENTS. Configure WAF rules for OWASP protection, implement network segmentation with micro-segmentation, deploy IDS/IPS systems, configure cloud security groups and NACLs, implement DDoS protection with rate limiting and geo-blocking."
|
||||
- Output: WAF configuration, network security policies, IDS/IPS rules, cloud security configurations
|
||||
- Context: Implements network-level defenses
|
||||
|
||||
### 10. Secrets Management Implementation
|
||||
- Use Task tool with subagent_type="deployment-strategies::deployment-engineer"
|
||||
- Prompt: "Implement enterprise secrets management for: $ARGUMENTS. Deploy HashiCorp Vault or AWS Secrets Manager, implement secret rotation policies, remove hardcoded secrets, configure least-privilege IAM roles, implement encryption key management with HSM support."
|
||||
- Output: Secrets management configuration, rotation policies, IAM role definitions, key management procedures
|
||||
- Context: Eliminates secrets exposure vulnerabilities
|
||||
|
||||
## Phase 4: Validation and Compliance
|
||||
|
||||
### 11. Penetration Testing and Validation
|
||||
- Use Task tool with subagent_type="security-auditor"
|
||||
- Prompt: "Execute comprehensive penetration testing for: $ARGUMENTS. Perform authenticated and unauthenticated testing, API security testing, business logic testing, privilege escalation attempts. Use Burp Suite, Metasploit, and custom exploits. Validate all security controls effectiveness."
|
||||
- Output: Penetration test report, proof-of-concept exploits, remediation validation, security control effectiveness metrics
|
||||
- Context: Validates all implemented security measures
|
||||
|
||||
### 12. Compliance and Standards Verification
|
||||
- Use Task tool with subagent_type="security-auditor"
|
||||
- Prompt: "Verify compliance with security frameworks for: $ARGUMENTS. Validate against OWASP ASVS Level 2, CIS Benchmarks, SOC2 Type II requirements, GDPR/CCPA privacy controls, HIPAA/PCI-DSS if applicable. Generate compliance attestation reports."
|
||||
- Output: Compliance assessment report, gap analysis, remediation requirements, audit evidence collection
|
||||
- Context: Ensures regulatory and industry standard compliance
|
||||
|
||||
### 13. Security Monitoring and SIEM Integration
|
||||
- Use Task tool with subagent_type="incident-response::devops-troubleshooter"
|
||||
- Prompt: "Implement security monitoring and SIEM for: $ARGUMENTS. Deploy Splunk/ELK/Sentinel integration, configure security event correlation, implement behavioral analytics for anomaly detection, set up automated incident response playbooks, create security dashboards and alerting."
|
||||
- Output: SIEM configuration, correlation rules, incident response playbooks, security dashboards, alert definitions
|
||||
- Context: Establishes continuous security monitoring
|
||||
|
||||
## Configuration Options
|
||||
- scanning_depth: "quick" | "standard" | "comprehensive" (default: comprehensive)
|
||||
- compliance_frameworks: ["OWASP", "CIS", "SOC2", "GDPR", "HIPAA", "PCI-DSS"]
|
||||
- remediation_priority: "cvss_score" | "exploitability" | "business_impact"
|
||||
- monitoring_integration: "splunk" | "elastic" | "sentinel" | "custom"
|
||||
- authentication_methods: ["oauth2", "saml", "mfa", "biometric", "passwordless"]
|
||||
|
||||
## Success Criteria
|
||||
- All critical vulnerabilities (CVSS 7+) remediated
|
||||
- OWASP Top 10 vulnerabilities addressed
|
||||
- Zero high-risk findings in penetration testing
|
||||
- Compliance frameworks validation passed
|
||||
- Security monitoring detecting and alerting on threats
|
||||
- Incident response time < 15 minutes for critical alerts
|
||||
- SBOM generated and vulnerabilities tracked
|
||||
- All secrets managed through secure vault
|
||||
- Authentication implements MFA and secure session management
|
||||
- Security tests integrated into CI/CD pipeline
|
||||
|
||||
## Coordination Notes
|
||||
- Each phase provides detailed findings that inform subsequent phases
|
||||
- Security-auditor agent coordinates with domain-specific agents for fixes
|
||||
- All code changes undergo security review before implementation
|
||||
- Continuous feedback loop between assessment and remediation
|
||||
- Security findings tracked in centralized vulnerability management system
|
||||
- Regular security reviews scheduled post-implementation
|
||||
|
||||
Security hardening target: $ARGUMENTS
|
||||
473
commands/security-sast.md
Normal file
473
commands/security-sast.md
Normal file
@@ -0,0 +1,473 @@
|
||||
---
|
||||
description: Static Application Security Testing (SAST) for code vulnerability analysis across multiple languages and frameworks
|
||||
globs: ['**/*.py', '**/*.js', '**/*.ts', '**/*.java', '**/*.rb', '**/*.go', '**/*.rs', '**/*.php']
|
||||
keywords: [sast, static analysis, code security, vulnerability scanning, bandit, semgrep, eslint, sonarqube, codeql, security patterns, code review, ast analysis]
|
||||
---
|
||||
|
||||
# SAST Security Plugin
|
||||
|
||||
Static Application Security Testing (SAST) for comprehensive code vulnerability detection across multiple languages, frameworks, and security patterns.
|
||||
|
||||
## Capabilities
|
||||
|
||||
- **Multi-language SAST**: Python, JavaScript/TypeScript, Java, Ruby, PHP, Go, Rust
|
||||
- **Tool integration**: Bandit, Semgrep, ESLint Security, SonarQube, CodeQL, PMD, SpotBugs, Brakeman, gosec, cargo-clippy
|
||||
- **Vulnerability patterns**: SQL injection, XSS, hardcoded secrets, path traversal, IDOR, CSRF, insecure deserialization
|
||||
- **Framework analysis**: Django, Flask, React, Express, Spring Boot, Rails, Laravel
|
||||
- **Custom rule authoring**: Semgrep pattern development for organization-specific security policies
|
||||
|
||||
## When to Use This Tool
|
||||
|
||||
Use for code review security analysis, injection vulnerabilities, hardcoded secrets, framework-specific patterns, custom security policy enforcement, pre-deployment validation, legacy code assessment, and compliance (OWASP, PCI-DSS, SOC2).
|
||||
|
||||
**Specialized tools**: Use `security-secrets.md` for advanced credential scanning, `security-owasp.md` for Top 10 mapping, `security-api.md` for REST/GraphQL endpoints.
|
||||
|
||||
## SAST Tool Selection
|
||||
|
||||
### Python: Bandit
|
||||
|
||||
```bash
|
||||
# Installation & scan
|
||||
pip install bandit
|
||||
bandit -r . -f json -o bandit-report.json
|
||||
bandit -r . -ll -ii -f json # High/Critical only
|
||||
```
|
||||
|
||||
**Configuration**: `.bandit`
|
||||
```yaml
|
||||
exclude_dirs: ['/tests/', '/venv/', '/.tox/', '/build/']
|
||||
tests: [B201, B301, B302, B303, B304, B305, B307, B308, B312, B323, B324, B501, B502, B506, B602, B608]
|
||||
skips: [B101]
|
||||
```
|
||||
|
||||
### JavaScript/TypeScript: ESLint Security
|
||||
|
||||
```bash
|
||||
npm install --save-dev eslint @eslint/plugin-security eslint-plugin-no-secrets
|
||||
eslint . --ext .js,.jsx,.ts,.tsx --format json > eslint-security.json
|
||||
```
|
||||
|
||||
**Configuration**: `.eslintrc-security.json`
|
||||
```json
|
||||
{
|
||||
"plugins": ["@eslint/plugin-security", "eslint-plugin-no-secrets"],
|
||||
"extends": ["plugin:security/recommended"],
|
||||
"rules": {
|
||||
"security/detect-object-injection": "error",
|
||||
"security/detect-non-literal-fs-filename": "error",
|
||||
"security/detect-eval-with-expression": "error",
|
||||
"security/detect-pseudo-random-prng": "error",
|
||||
"no-secrets/no-secrets": "error"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Multi-Language: Semgrep
|
||||
|
||||
```bash
|
||||
pip install semgrep
|
||||
semgrep --config=auto --json --output=semgrep-report.json
|
||||
semgrep --config=p/security-audit --json
|
||||
semgrep --config=p/owasp-top-ten --json
|
||||
semgrep ci --config=auto # CI mode
|
||||
```
|
||||
|
||||
**Custom Rules**: `.semgrep.yml`
|
||||
```yaml
|
||||
rules:
|
||||
- id: sql-injection-format-string
|
||||
pattern: cursor.execute("... %s ..." % $VAR)
|
||||
message: SQL injection via string formatting
|
||||
severity: ERROR
|
||||
languages: [python]
|
||||
metadata:
|
||||
cwe: "CWE-89"
|
||||
owasp: "A03:2021-Injection"
|
||||
|
||||
- id: dangerous-innerHTML
|
||||
pattern: $ELEM.innerHTML = $VAR
|
||||
message: XSS via innerHTML assignment
|
||||
severity: ERROR
|
||||
languages: [javascript, typescript]
|
||||
metadata:
|
||||
cwe: "CWE-79"
|
||||
|
||||
- id: hardcoded-aws-credentials
|
||||
patterns:
|
||||
- pattern: $KEY = "AKIA..."
|
||||
- metavariable-regex:
|
||||
metavariable: $KEY
|
||||
regex: "(aws_access_key_id|AWS_ACCESS_KEY_ID)"
|
||||
message: Hardcoded AWS credentials detected
|
||||
severity: ERROR
|
||||
languages: [python, javascript, java]
|
||||
|
||||
- id: path-traversal-open
|
||||
patterns:
|
||||
- pattern: open($PATH, ...)
|
||||
- pattern-not: open(os.path.join(SAFE_DIR, ...), ...)
|
||||
- metavariable-pattern:
|
||||
metavariable: $PATH
|
||||
patterns:
|
||||
- pattern: $REQ.get(...)
|
||||
message: Path traversal via user input
|
||||
severity: ERROR
|
||||
languages: [python]
|
||||
|
||||
- id: command-injection
|
||||
patterns:
|
||||
- pattern-either:
|
||||
- pattern: os.system($CMD)
|
||||
- pattern: subprocess.call($CMD, shell=True)
|
||||
- metavariable-pattern:
|
||||
metavariable: $CMD
|
||||
patterns:
|
||||
- pattern-either:
|
||||
- pattern: $X + $Y
|
||||
- pattern: f"...{$VAR}..."
|
||||
message: Command injection via shell=True
|
||||
severity: ERROR
|
||||
languages: [python]
|
||||
```
|
||||
|
||||
### Other Language Tools
|
||||
|
||||
**Java**: `mvn spotbugs:check`
|
||||
**Ruby**: `brakeman -o report.json -f json`
|
||||
**Go**: `gosec -fmt=json -out=gosec.json ./...`
|
||||
**Rust**: `cargo clippy -- -W clippy::unwrap_used`
|
||||
|
||||
## Vulnerability Patterns
|
||||
|
||||
### SQL Injection
|
||||
|
||||
**VULNERABLE**: String formatting/concatenation with user input in SQL queries
|
||||
|
||||
**SECURE**:
|
||||
```python
|
||||
# Parameterized queries
|
||||
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
|
||||
User.objects.filter(id=user_id) # ORM
|
||||
```
|
||||
|
||||
### Cross-Site Scripting (XSS)
|
||||
|
||||
**VULNERABLE**: Direct HTML manipulation with unsanitized user input (innerHTML, outerHTML, document.write)
|
||||
|
||||
**SECURE**:
|
||||
```javascript
|
||||
// Use textContent for plain text
|
||||
element.textContent = userInput;
|
||||
|
||||
// React auto-escapes
|
||||
<div>{userInput}</div>
|
||||
|
||||
// Sanitize when HTML required
|
||||
import DOMPurify from 'dompurify';
|
||||
element.innerHTML = DOMPurify.sanitize(userInput);
|
||||
```
|
||||
|
||||
### Hardcoded Secrets
|
||||
|
||||
**VULNERABLE**: Hardcoded API keys, passwords, tokens in source code
|
||||
|
||||
**SECURE**:
|
||||
```python
|
||||
import os
|
||||
API_KEY = os.environ.get('API_KEY')
|
||||
PASSWORD = os.getenv('DB_PASSWORD')
|
||||
```
|
||||
|
||||
### Path Traversal
|
||||
|
||||
**VULNERABLE**: Opening files using unsanitized user input
|
||||
|
||||
**SECURE**:
|
||||
```python
|
||||
import os
|
||||
ALLOWED_DIR = '/var/www/uploads'
|
||||
file_name = request.args.get('file')
|
||||
file_path = os.path.join(ALLOWED_DIR, file_name)
|
||||
file_path = os.path.realpath(file_path)
|
||||
if not file_path.startswith(os.path.realpath(ALLOWED_DIR)):
|
||||
raise ValueError("Invalid file path")
|
||||
with open(file_path, 'r') as f:
|
||||
content = f.read()
|
||||
```
|
||||
|
||||
### Insecure Deserialization
|
||||
|
||||
**VULNERABLE**: pickle.loads(), yaml.load() with untrusted data
|
||||
|
||||
**SECURE**:
|
||||
```python
|
||||
import json
|
||||
data = json.loads(user_input) # SECURE
|
||||
import yaml
|
||||
config = yaml.safe_load(user_input) # SECURE
|
||||
```
|
||||
|
||||
### Command Injection
|
||||
|
||||
**VULNERABLE**: os.system() or subprocess with shell=True and user input
|
||||
|
||||
**SECURE**:
|
||||
```python
|
||||
subprocess.run(['ping', '-c', '4', user_input]) # Array args
|
||||
import shlex
|
||||
safe_input = shlex.quote(user_input) # Input validation
|
||||
```
|
||||
|
||||
### Insecure Random
|
||||
|
||||
**VULNERABLE**: random module for security-critical operations
|
||||
|
||||
**SECURE**:
|
||||
```python
|
||||
import secrets
|
||||
token = secrets.token_hex(16)
|
||||
session_id = secrets.token_urlsafe(32)
|
||||
```
|
||||
|
||||
## Framework Security
|
||||
|
||||
### Django
|
||||
|
||||
**VULNERABLE**: @csrf_exempt, DEBUG=True, weak SECRET_KEY, missing security middleware
|
||||
|
||||
**SECURE**:
|
||||
```python
|
||||
# settings.py
|
||||
DEBUG = False
|
||||
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
]
|
||||
|
||||
SECURE_SSL_REDIRECT = True
|
||||
SESSION_COOKIE_SECURE = True
|
||||
CSRF_COOKIE_SECURE = True
|
||||
X_FRAME_OPTIONS = 'DENY'
|
||||
```
|
||||
|
||||
### Flask
|
||||
|
||||
**VULNERABLE**: debug=True, weak secret_key, CORS wildcard
|
||||
|
||||
**SECURE**:
|
||||
```python
|
||||
import os
|
||||
from flask_talisman import Talisman
|
||||
|
||||
app.secret_key = os.environ.get('FLASK_SECRET_KEY')
|
||||
Talisman(app, force_https=True)
|
||||
CORS(app, origins=['https://example.com'])
|
||||
```
|
||||
|
||||
### Express.js
|
||||
|
||||
**VULNERABLE**: Missing helmet, CORS wildcard, no rate limiting
|
||||
|
||||
**SECURE**:
|
||||
```javascript
|
||||
const helmet = require('helmet');
|
||||
const rateLimit = require('express-rate-limit');
|
||||
|
||||
app.use(helmet());
|
||||
app.use(cors({ origin: 'https://example.com' }));
|
||||
app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }));
|
||||
```
|
||||
|
||||
## Multi-Language Scanner Implementation
|
||||
|
||||
```python
|
||||
import json
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Any
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
|
||||
@dataclass
|
||||
class SASTFinding:
|
||||
tool: str
|
||||
severity: str
|
||||
category: str
|
||||
title: str
|
||||
description: str
|
||||
file_path: str
|
||||
line_number: int
|
||||
cwe: str
|
||||
owasp: str
|
||||
confidence: str
|
||||
|
||||
class MultiLanguageSASTScanner:
|
||||
def __init__(self, project_path: str):
|
||||
self.project_path = Path(project_path)
|
||||
self.findings: List[SASTFinding] = []
|
||||
|
||||
def detect_languages(self) -> List[str]:
|
||||
"""Auto-detect languages"""
|
||||
languages = []
|
||||
indicators = {
|
||||
'python': ['*.py', 'requirements.txt'],
|
||||
'javascript': ['*.js', 'package.json'],
|
||||
'typescript': ['*.ts', 'tsconfig.json'],
|
||||
'java': ['*.java', 'pom.xml'],
|
||||
'ruby': ['*.rb', 'Gemfile'],
|
||||
'go': ['*.go', 'go.mod'],
|
||||
'rust': ['*.rs', 'Cargo.toml'],
|
||||
}
|
||||
for lang, patterns in indicators.items():
|
||||
for pattern in patterns:
|
||||
if list(self.project_path.glob(f'**/{pattern}')):
|
||||
languages.append(lang)
|
||||
break
|
||||
return languages
|
||||
|
||||
def run_comprehensive_sast(self) -> Dict[str, Any]:
|
||||
"""Execute all applicable SAST tools"""
|
||||
languages = self.detect_languages()
|
||||
|
||||
scan_results = {
|
||||
'timestamp': datetime.now().isoformat(),
|
||||
'languages': languages,
|
||||
'tools_executed': [],
|
||||
'findings': []
|
||||
}
|
||||
|
||||
self.run_semgrep_scan()
|
||||
scan_results['tools_executed'].append('semgrep')
|
||||
|
||||
if 'python' in languages:
|
||||
self.run_bandit_scan()
|
||||
scan_results['tools_executed'].append('bandit')
|
||||
if 'javascript' in languages or 'typescript' in languages:
|
||||
self.run_eslint_security_scan()
|
||||
scan_results['tools_executed'].append('eslint-security')
|
||||
|
||||
scan_results['findings'] = [vars(f) for f in self.findings]
|
||||
scan_results['summary'] = self.generate_summary()
|
||||
return scan_results
|
||||
|
||||
def run_semgrep_scan(self):
|
||||
"""Run Semgrep"""
|
||||
for ruleset in ['auto', 'p/security-audit', 'p/owasp-top-ten']:
|
||||
try:
|
||||
result = subprocess.run([
|
||||
'semgrep', '--config', ruleset, '--json', '--quiet',
|
||||
str(self.project_path)
|
||||
], capture_output=True, text=True, timeout=300)
|
||||
|
||||
if result.stdout:
|
||||
data = json.loads(result.stdout)
|
||||
for f in data.get('results', []):
|
||||
self.findings.append(SASTFinding(
|
||||
tool='semgrep',
|
||||
severity=f.get('extra', {}).get('severity', 'MEDIUM').upper(),
|
||||
category='sast',
|
||||
title=f.get('check_id', ''),
|
||||
description=f.get('extra', {}).get('message', ''),
|
||||
file_path=f.get('path', ''),
|
||||
line_number=f.get('start', {}).get('line', 0),
|
||||
cwe=f.get('extra', {}).get('metadata', {}).get('cwe', ''),
|
||||
owasp=f.get('extra', {}).get('metadata', {}).get('owasp', ''),
|
||||
confidence=f.get('extra', {}).get('metadata', {}).get('confidence', 'MEDIUM')
|
||||
))
|
||||
except Exception as e:
|
||||
print(f"Semgrep {ruleset} failed: {e}")
|
||||
|
||||
def generate_summary(self) -> Dict[str, Any]:
|
||||
"""Generate statistics"""
|
||||
severity_counts = {'CRITICAL': 0, 'HIGH': 0, 'MEDIUM': 0, 'LOW': 0}
|
||||
for f in self.findings:
|
||||
severity_counts[f.severity] = severity_counts.get(f.severity, 0) + 1
|
||||
|
||||
return {
|
||||
'total_findings': len(self.findings),
|
||||
'severity_breakdown': severity_counts,
|
||||
'risk_score': self.calculate_risk_score(severity_counts)
|
||||
}
|
||||
|
||||
def calculate_risk_score(self, severity_counts: Dict[str, int]) -> int:
|
||||
"""Risk score 0-100"""
|
||||
weights = {'CRITICAL': 10, 'HIGH': 7, 'MEDIUM': 4, 'LOW': 1}
|
||||
total = sum(weights[s] * c for s, c in severity_counts.items())
|
||||
return min(100, int((total / 50) * 100))
|
||||
```
|
||||
|
||||
## CI/CD Integration
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
```yaml
|
||||
name: SAST Scan
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
sast:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install tools
|
||||
run: |
|
||||
pip install bandit semgrep
|
||||
npm install -g eslint @eslint/plugin-security
|
||||
|
||||
- name: Run scans
|
||||
run: |
|
||||
bandit -r . -f json -o bandit.json || true
|
||||
semgrep --config=auto --json --output=semgrep.json || true
|
||||
|
||||
- name: Upload reports
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: sast-reports
|
||||
path: |
|
||||
bandit.json
|
||||
semgrep.json
|
||||
```
|
||||
|
||||
### GitLab CI
|
||||
|
||||
```yaml
|
||||
sast:
|
||||
stage: test
|
||||
image: python:3.11
|
||||
script:
|
||||
- pip install bandit semgrep
|
||||
- bandit -r . -f json -o bandit.json || true
|
||||
- semgrep --config=auto --json --output=semgrep.json || true
|
||||
artifacts:
|
||||
reports:
|
||||
sast: bandit.json
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Run early and often** - Pre-commit hooks and CI/CD
|
||||
2. **Combine multiple tools** - Different tools catch different vulnerabilities
|
||||
3. **Tune false positives** - Configure exclusions and thresholds
|
||||
4. **Prioritize findings** - Focus on CRITICAL/HIGH first
|
||||
5. **Framework-aware scanning** - Use specific rulesets
|
||||
6. **Custom rules** - Organization-specific patterns
|
||||
7. **Developer training** - Secure coding practices
|
||||
8. **Incremental remediation** - Fix gradually
|
||||
9. **Baseline management** - Track known issues
|
||||
10. **Regular updates** - Keep tools current
|
||||
|
||||
## Related Tools
|
||||
|
||||
- **security-secrets.md** - Advanced credential detection
|
||||
- **security-owasp.md** - OWASP Top 10 assessment
|
||||
- **security-api.md** - API security testing
|
||||
- **security-scan.md** - Comprehensive security scanning
|
||||
Reference in New Issue
Block a user