119 lines
3.9 KiB
Python
119 lines
3.9 KiB
Python
import subprocess
|
||
import json
|
||
import sys
|
||
import os
|
||
|
||
|
||
def audit_npm():
|
||
if not os.path.exists("package.json"):
|
||
return None
|
||
|
||
print("🛡️ Executando auditoria de segurança (npm)...")
|
||
try:
|
||
result = subprocess.run(
|
||
["npm", "audit", "--json"], capture_output=True, text=True, shell=True
|
||
)
|
||
if not result.stdout:
|
||
return "❌ Erro ao rodar npm audit: Nenhuma saída gerada."
|
||
output = json.loads(result.stdout)
|
||
except Exception as e:
|
||
return f"❌ Falha ao rodar npm audit: {e}"
|
||
|
||
vulns = output.get("vulnerabilities", {})
|
||
metadata = output.get("metadata", {}).get("vulnerabilities", {})
|
||
total_high = metadata.get("high", 0)
|
||
total_crit = metadata.get("critical", 0)
|
||
|
||
if total_high == 0 and total_crit == 0:
|
||
return "✅ NPM: Nenhuma vulnerabilidade Alta ou Crítica."
|
||
|
||
report = [f"🚨 NPM: {total_high} Altas e {total_crit} Críticas."]
|
||
for name, data in vulns.items():
|
||
severity = data.get("severity", "low")
|
||
if severity in ["high", "critical"]:
|
||
report.append(
|
||
f"- [{severity.upper()}] {name} (Fix? {'Sim' if data.get('fixAvailable') else 'Não'})"
|
||
)
|
||
return "\n".join(report)
|
||
|
||
|
||
def audit_python():
|
||
# Procura por arquivos de dependência python
|
||
py_deps = ["requirements.txt", ".agent/tools/requirements.txt"]
|
||
target_file = next((f for f in py_deps if os.path.exists(f)), None)
|
||
|
||
if not target_file:
|
||
return None
|
||
|
||
print(f"🐍 Executando auditoria de segurança (python-audit via {target_file})...")
|
||
try:
|
||
# Tenta usar pip-audit (mais moderno)
|
||
result = subprocess.run(
|
||
["python", "-m", "pip_audit", "-r", target_file, "--format", "json"],
|
||
capture_output=True,
|
||
text=True,
|
||
shell=True,
|
||
)
|
||
|
||
if result.returncode != 0 and not result.stdout:
|
||
# Se falhar e não tiver saída, pode ser que o pip-audit não esteja instalado
|
||
return "⚠️ pip-audit não instalado. Instale com: pip install pip-audit"
|
||
|
||
# pip-audit retorna 0 se não houver vulns, >0 se houver
|
||
output = json.loads(result.stdout)
|
||
|
||
vulns_found = []
|
||
# A saída pode ser um dicionário com uma lista ou uma lista dependendo da versão/formato
|
||
packages = (
|
||
output if isinstance(output, list) else output.get("dependencies", [])
|
||
)
|
||
|
||
for package in packages:
|
||
if not isinstance(package, dict):
|
||
continue
|
||
for vuln in package.get("vulnerabilities", []):
|
||
vulns_found.append(
|
||
{
|
||
"name": package["name"],
|
||
"version": package["version"],
|
||
"id": vuln["id"],
|
||
"fix": vuln.get("fix_versions", ["N/A"]),
|
||
}
|
||
)
|
||
|
||
if not vulns_found:
|
||
return "✅ Python: Nenhuma vulnerabilidade encontrada."
|
||
|
||
report = [f"🚨 PYTHON: {len(vulns_found)} vulnerabilidades encontradas."]
|
||
for v in vulns_found:
|
||
report.append(
|
||
f"- {v['name']} ({v['version']}) -> ID: {v['id']} (Fix: {', '.join(v['fix'])})"
|
||
)
|
||
return "\n".join(report)
|
||
|
||
except Exception as e:
|
||
# Fallback se pip-audit falhar por não existir ou erro de parse
|
||
print(f"⚠️ Erro ao executar auditoria Python: {e}")
|
||
return "⚠️ pip-audit falhou ou não foi inicializado corretamente."
|
||
|
||
|
||
def audit_security():
|
||
reports = []
|
||
|
||
npm_report = audit_npm()
|
||
if npm_report:
|
||
reports.append(npm_report)
|
||
|
||
py_report = audit_python()
|
||
if py_report:
|
||
reports.append(py_report)
|
||
|
||
if not reports:
|
||
return "ℹ️ Nenhum arquivo de dependência encontrado (package.json ou requirements.txt)."
|
||
|
||
return "\n\n".join(reports)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
print(audit_security())
|