home / skills / aj-geddes / useful-ai-prompts / vulnerability-scanning
This skill automates vulnerability scanning across dependencies, code, containers, and infrastructure to accelerate security audits and ongoing risk management.
npx playbooks add skill aj-geddes/useful-ai-prompts --skill vulnerability-scanningReview the files below or copy the command above to add this skill to your agents.
---
name: vulnerability-scanning
description: Automated vulnerability detection using OWASP tools, CVE databases, and security scanners. Use when performing security audits, compliance checks, or continuous security monitoring.
---
# Vulnerability Scanning
## Overview
Systematically identify security vulnerabilities in applications, dependencies, and infrastructure using automated scanning tools and manual security assessments.
## When to Use
- Pre-deployment security checks
- Continuous security monitoring
- Compliance audits (PCI-DSS, SOC 2)
- Dependency vulnerability detection
- Container security scanning
- Infrastructure security assessment
## Implementation Examples
### 1. **Node.js Vulnerability Scanner**
```javascript
// scanner.js - Comprehensive vulnerability scanning
const { exec } = require('child_process');
const util = require('util');
const fs = require('fs').promises;
const execPromise = util.promisify(exec);
class VulnerabilityScanner {
constructor() {
this.results = {
dependencies: [],
code: [],
docker: [],
secrets: []
};
}
async scanDependencies() {
console.log('Scanning dependencies with npm audit...');
try {
const { stdout } = await execPromise('npm audit --json');
const auditResults = JSON.parse(stdout);
for (const [name, advisory] of Object.entries(auditResults.vulnerabilities || {})) {
this.results.dependencies.push({
package: name,
severity: advisory.severity,
cve: advisory.via.filter(v => typeof v === 'object').map(v => v.cve),
title: advisory.via.filter(v => typeof v === 'object').map(v => v.title),
vulnerableVersions: advisory.range,
recommendation: advisory.fixAvailable ? 'Update available' : 'No fix available'
});
}
} catch (error) {
console.error('Dependency scan failed:', error.message);
}
}
async scanCode() {
console.log('Scanning code with ESLint security plugin...');
try {
const { stdout } = await execPromise('npx eslint . --format json --plugin security');
const eslintResults = JSON.parse(stdout);
for (const file of eslintResults) {
for (const message of file.messages) {
if (message.ruleId && message.ruleId.includes('security')) {
this.results.code.push({
file: file.filePath,
line: message.line,
column: message.column,
rule: message.ruleId,
severity: message.severity === 2 ? 'high' : 'medium',
message: message.message
});
}
}
}
} catch (error) {
console.log('Code scan completed with findings');
}
}
async scanDockerfile() {
console.log('Scanning Dockerfile with hadolint...');
try {
const { stdout } = await execPromise('hadolint Dockerfile --format json');
const hadolintResults = JSON.parse(stdout);
for (const issue of hadolintResults) {
this.results.docker.push({
line: issue.line,
level: issue.level,
code: issue.code,
message: issue.message
});
}
} catch (error) {
console.log('Dockerfile scan completed');
}
}
async scanSecrets() {
console.log('Scanning for secrets with truffleHog...');
try {
const { stdout } = await execPromise('trufflehog filesystem . --json');
const lines = stdout.trim().split('\n');
for (const line of lines) {
if (line) {
const finding = JSON.parse(line);
this.results.secrets.push({
file: finding.SourceMetadata?.Data?.Filesystem?.file,
line: finding.SourceMetadata?.Data?.Filesystem?.line,
type: finding.DetectorName,
verified: finding.Verified
});
}
}
} catch (error) {
console.log('Secret scan completed');
}
}
async runFullScan() {
await this.scanDependencies();
await this.scanCode();
await this.scanDockerfile();
await this.scanSecrets();
return this.generateReport();
}
generateReport() {
const report = {
timestamp: new Date().toISOString(),
summary: {
critical: 0,
high: 0,
medium: 0,
low: 0
},
findings: this.results,
totalIssues: 0
};
// Count by severity
for (const dep of this.results.dependencies) {
report.summary[dep.severity]++;
report.totalIssues++;
}
for (const code of this.results.code) {
report.summary[code.severity]++;
report.totalIssues++;
}
// High severity for secrets
report.summary.high += this.results.secrets.filter(s => s.verified).length;
report.totalIssues += this.results.secrets.length;
return report;
}
}
// Usage
async function main() {
const scanner = new VulnerabilityScanner();
const report = await scanner.runFullScan();
await fs.writeFile('security-report.json', JSON.stringify(report, null, 2));
console.log('\n=== Security Scan Summary ===');
console.log(`Total Issues: ${report.totalIssues}`);
console.log(`Critical: ${report.summary.critical}`);
console.log(`High: ${report.summary.high}`);
console.log(`Medium: ${report.summary.medium}`);
console.log(`Low: ${report.summary.low}`);
}
main().catch(console.error);
```
### 2. **Python OWASP Scanner**
```python
# owasp_scanner.py
import subprocess
import json
import os
from typing import Dict, List
from dataclasses import dataclass, asdict
from datetime import datetime
@dataclass
class Vulnerability:
severity: str
cve: str
package: str
version: str
description: str
fix: str
class OWASPScanner:
def __init__(self, project_path: str):
self.project_path = project_path
self.vulnerabilities: List[Vulnerability] = []
def scan_dependencies(self) -> None:
"""Scan Python dependencies using Safety"""
print("Scanning dependencies with Safety...")
try:
result = subprocess.run(
['safety', 'check', '--json', '--file', 'requirements.txt'],
cwd=self.project_path,
capture_output=True,
text=True
)
if result.stdout:
findings = json.loads(result.stdout)
for vuln in findings:
self.vulnerabilities.append(Vulnerability(
severity=self._map_severity(vuln.get('severity', 'unknown')),
cve=vuln.get('cve', 'N/A'),
package=vuln.get('package_name', ''),
version=vuln.get('analyzed_version', ''),
description=vuln.get('advisory', ''),
fix=f"Upgrade to {vuln.get('fixed_versions', 'latest')}"
))
except Exception as e:
print(f"Dependency scan error: {e}")
def scan_with_bandit(self) -> None:
"""Scan Python code with Bandit"""
print("Scanning code with Bandit...")
try:
result = subprocess.run(
['bandit', '-r', '.', '-f', 'json'],
cwd=self.project_path,
capture_output=True,
text=True
)
if result.stdout:
findings = json.loads(result.stdout)
for issue in findings.get('results', []):
self.vulnerabilities.append(Vulnerability(
severity=issue['issue_severity'].lower(),
cve='BANDIT-' + issue['test_id'],
package=os.path.basename(issue['filename']),
version=str(issue['line_number']),
description=f"{issue['issue_text']} - {issue['test_name']}",
fix=issue.get('more_info', 'Review code')
))
except Exception as e:
print(f"Bandit scan error: {e}")
def scan_with_trivy(self) -> None:
"""Scan container images with Trivy"""
print("Scanning container with Trivy...")
try:
result = subprocess.run(
['trivy', 'image', '--format', 'json', 'myapp:latest'],
capture_output=True,
text=True
)
if result.stdout:
findings = json.loads(result.stdout)
for result_item in findings.get('Results', []):
for vuln in result_item.get('Vulnerabilities', []):
self.vulnerabilities.append(Vulnerability(
severity=vuln['Severity'].lower(),
cve=vuln.get('VulnerabilityID', 'N/A'),
package=vuln['PkgName'],
version=vuln['InstalledVersion'],
description=vuln.get('Title', vuln.get('Description', '')),
fix=vuln.get('FixedVersion', 'No fix available')
))
except Exception as e:
print(f"Trivy scan error: {e}")
def _map_severity(self, severity: str) -> str:
mapping = {
'critical': 'critical',
'high': 'high',
'medium': 'medium',
'low': 'low'
}
return mapping.get(severity.lower(), 'medium')
def generate_report(self) -> Dict:
summary = {
'critical': 0,
'high': 0,
'medium': 0,
'low': 0
}
for vuln in self.vulnerabilities:
if vuln.severity in summary:
summary[vuln.severity] += 1
return {
'timestamp': datetime.now().isoformat(),
'total_vulnerabilities': len(self.vulnerabilities),
'summary': summary,
'vulnerabilities': [asdict(v) for v in self.vulnerabilities],
'compliance_status': 'FAIL' if summary['critical'] > 0 or summary['high'] > 0 else 'PASS'
}
def run_full_scan(self) -> Dict:
self.scan_dependencies()
self.scan_with_bandit()
self.scan_with_trivy()
report = self.generate_report()
with open('owasp-scan-report.json', 'w') as f:
json.dump(report, f, indent=2)
return report
# Usage
if __name__ == '__main__':
scanner = OWASPScanner('.')
report = scanner.run_full_scan()
print(f"\n=== OWASP Scan Complete ===")
print(f"Total Vulnerabilities: {report['total_vulnerabilities']}")
print(f"Critical: {report['summary']['critical']}")
print(f"High: {report['summary']['high']}")
print(f"Compliance Status: {report['compliance_status']}")
```
### 3. **CI/CD Integration - GitHub Actions**
```yaml
# .github/workflows/security-scan.yml
name: Security Vulnerability Scan
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 2 * * *' # Daily at 2 AM
jobs:
vulnerability-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH,MEDIUM'
- name: Upload Trivy results to GitHub Security
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
- name: Run Snyk Security Scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high
- name: OWASP Dependency Check
uses: dependency-check/Dependency-Check_Action@main
with:
project: 'myapp'
path: '.'
format: 'JSON'
- name: Fail on high severity
run: |
if [ -f trivy-results.sarif ]; then
HIGH_COUNT=$(jq '.runs[].results | length' trivy-results.sarif)
if [ $HIGH_COUNT -gt 0 ]; then
echo "Found $HIGH_COUNT high severity vulnerabilities"
exit 1
fi
fi
```
## Best Practices
### ✅ DO
- Automate scans in CI/CD
- Scan dependencies regularly
- Use multiple scanning tools
- Set severity thresholds
- Track vulnerability trends
- Scan containers and images
- Monitor CVE databases
- Document false positives
### ❌ DON'T
- Skip vulnerability scanning
- Ignore low severity issues
- Trust single scanning tool
- Bypass security gates
- Commit secrets to repos
## Common Vulnerability Types
- **CVE**: Known vulnerabilities in libraries
- **CWE**: Common weakness patterns
- **OWASP Top 10**: Web application risks
- **Container vulnerabilities**: Base image issues
- **Dependency confusion**: Supply chain attacks
- **Secrets exposure**: Hardcoded credentials
## Scanning Tools
- **Trivy**: Container and filesystem scanner
- **Snyk**: Dependency and code scanning
- **OWASP Dependency Check**: Java, .NET, Node.js
- **Safety**: Python dependency checker
- **npm audit / yarn audit**: Node.js packages
- **Bandit**: Python security linter
- **Semgrep**: Static analysis tool
## Resources
- [OWASP Vulnerability Scanning Guide](https://owasp.org/www-community/Vulnerability_Scanning_Tools)
- [National Vulnerability Database](https://nvd.nist.gov/)
- [Trivy Documentation](https://aquasecurity.github.io/trivy/)
- [Snyk Vulnerability Database](https://snyk.io/vuln)
This skill automates vulnerability detection across applications, dependencies, containers, and infrastructure using OWASP tools, CVE sources, and popular security scanners. It consolidates results into actionable reports for audits, CI/CD gates, and continuous monitoring. Use it to find dependency CVEs, code issues, misconfigured containers, and leaked secrets before they reach production.
The scanner runs multiple tools (npm audit, Safety, Bandit, Trivy, hadolint, truffleHog, Snyk, OWASP Dependency Check) and normalizes findings into a single report with severity counts and recommended fixes. It can run locally, inside CI/CD pipelines, or on a schedule, and exports machine-readable outputs (JSON, SARIF) for dashboards or gating logic. The tool maps severities, aggregates duplicates, and highlights verified secrets and high-risk items that should fail the build.
Can this run in CI/CD pipelines?
Yes. Integrate the scanners into workflows (GitHub Actions, GitLab CI) and fail builds based on severity thresholds or policy rules.
Which tools should I run together?
Combine dependency scanners (Safety, npm audit, Snyk) with static code analyzers (Bandit, Semgrep) and container scanners (Trivy) to cover multiple risk vectors.