Agent Type
Security Scanning Agent with OpenClaw
A security agent orchestrates multiple scanners (Bandit, Semgrep, pip-audit, Trivy) to scan your code, dependencies, and Docker images; detects hardcoded secrets; and produces a consolidated severity-triaged report with actionable remediation guidance.
Required Tools and Scanners
pip install bandit pip-audit semgrep
# Trivy — container/IaC scanner
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh# agents/security-agent.yaml
name: security-agent
model: gpt-4o
temperature: 0.0
tools:
- code_scanner # wraps Bandit + Semgrep
- dep_audit # wraps pip-audit / npm audit
- config_checker # checks env files and config for secrets
- report_writer # structured report generation
system: |
You are an application security analyst.
Triage findings by CVSS severity: critical > high > medium > low > informational.
For each finding: state the file/line, describe the risk, and suggest a fix.
Group findings by severity. Always check for false positives before reporting.Source Code Vulnerability Scan
import subprocess, json, pathlib
from openclaw import Agent
agent = Agent.from_config("agents/security-agent.yaml")
def scan_python_code(directory: str) -> dict:
"""Run Bandit + Semgrep and summarise with AI."""
bandit_result = subprocess.run(
["bandit", "-r", directory, "-f", "json", "-q"],
capture_output=True, text=True, timeout=120
)
semgrep_result = subprocess.run(
["semgrep", "--config=auto", directory, "--json", "--quiet"],
capture_output=True, text=True, timeout=180
)
findings = {
"bandit": json.loads(bandit_result.stdout) if bandit_result.stdout else {},
"semgrep": json.loads(semgrep_result.stdout) if semgrep_result.stdout else {},
}
summary = agent.run(
"Analyse these security scan results and produce a triage summary.\n"
"Group by severity (CRITICAL/HIGH/MEDIUM/LOW).\n"
f"Data:\n{json.dumps(findings, indent=2)[:6000]}"
)
return {"findings": findings, "summary": summary}Dependency Audit
def audit_dependencies(requirements_file: str = "requirements.txt") -> str:
result = subprocess.run(
["pip-audit", "--requirement", requirements_file, "--format", "json"],
capture_output=True, text=True, timeout=120
)
vulns = json.loads(result.stdout) if result.stdout else []
if not vulns:
return "No known vulnerabilities found in Python dependencies."
return agent.run(
f"Found {len(vulns)} vulnerable dependencies. "
"For each: state severity, CVE, current version, safe upgrade version, "
"and whether it's a direct or transitive dependency.\n"
f"Data:\n{json.dumps(vulns, indent=2)[:6000]}"
)Hardcoded Secrets Detection
Never commit secrets to version control. The agent scans for API keys, passwords, and tokens in source files using pattern matching and entropy analysis.
import re, pathlib
# Common secret patterns — extend as needed
SECRET_PATTERNS = [
(r'(?i)(api[_-]?key|apikey)\s*[=:]\s*["\']?([A-Za-z0-9_\-]{20,})', "API Key"),
(r'(?i)(password|passwd|pwd)\s*[=:]\s*["\']([^"\']{8,})', "Password"),
(r'(?i)(secret|token)\s*[=:]\s*["\']([A-Za-z0-9_\-]{16,})', "Secret/Token"),
(r'sk-[A-Za-z0-9]{48}', "OpenAI Key"),
(r'ghp_[A-Za-z0-9]{36}', "GitHub Token"),
]
def scan_for_secrets(directory: str) -> list[dict]:
findings = []
for path in pathlib.Path(directory).rglob("*.py"):
# Skip virtual envs and test fixtures
if ".venv" in str(path) or "node_modules" in str(path):
continue
content = path.read_text(encoding="utf-8", errors="ignore")
for pattern, label in SECRET_PATTERNS:
for match in re.finditer(pattern, content):
line_num = content[:match.start()].count("\n") + 1
findings.append({
"file": str(path), "line": line_num,
"type": label, "match": match.group()[:60] + "...",
})
return findingsDocker Image Scanning (Trivy)
def scan_docker_image(image: str) -> str:
result = subprocess.run(
["trivy", "image", "--format", "json", "--quiet", image],
capture_output=True, text=True, timeout=300
)
trivy_data = json.loads(result.stdout) if result.stdout else {}
return agent.run(
f"Trivy scan of Docker image '{image}' complete. "
"Summarise critical and high CVEs. "
"Group by OS package vs. application library. "
"Suggest base image upgrade if OS CVEs are present.\n"
f"Data:\n{json.dumps(trivy_data, indent=2)[:6000]}"
)Scheduled Weekly Security Scan
import datetime, pathlib
def weekly_security_scan(repo_path: str, output_dir: str = "./security-reports") -> str:
"""Full security scan pipeline — run weekly via cron."""
output = pathlib.Path(output_dir)
output.mkdir(parents=True, exist_ok=True)
code_result = scan_python_code(repo_path)
dep_result = audit_dependencies(f"{repo_path}/requirements.txt")
secret_findings = scan_for_secrets(repo_path)
full_report = agent.run(
"Generate a complete Security Audit Report in Markdown format.\n"
"## Executive Summary\n## Critical Findings\n## High Findings\n"
"## Dependency Vulnerabilities\n## Secrets Detected\n## Recommendations\n"
f"Code scan summary: {code_result['summary']}\n"
f"Dependency audit: {dep_result}\n"
f"Secrets found: {len(secret_findings)} items\n"
)
date_str = datetime.date.today().isoformat()
report_path = output / f"security-report-{date_str}.md"
report_path.write_text(full_report, encoding="utf-8")
return str(report_path)# cron: weekly security scan every Monday at 02:00
0 2 * * 1 /usr/bin/python3 /opt/openclaw/security_scan.py --repo=/app >> /var/log/security-agent.log 2>&1