mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 13:44:56 +03:00
c47eed6a64
- Fix 25 shell=True subprocess calls with list-based commands - Fix 49 verify=False in defensive skills (env-var override) - Add timeout to 231 HTTP/subprocess/socket calls - Fix 6 SQL injection patterns with whitelist validation - Replace 8 __import__() with standard imports - Remove 701 unused imports across 442 files - Add authorized-testing disclaimers to all offensive skills - Complete 11 incomplete skill directories - Expand 10 stub SKILL.md files with full content - Fix 2 YAML parse errors in frontmatter - Fix 5 pre-existing syntax errors - Convert 22 hardcoded paths/ports to environment variables - Back up 21 redundant skill pairs to .bak - Fix 2 global declaration errors - 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE) - 0 compile errors across all 724 agent.py files
165 lines
5.6 KiB
Python
165 lines
5.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Supply chain malware artifact analysis agent.
|
|
|
|
Analyzes software supply chain compromise indicators including package
|
|
integrity, build pipeline artifacts, dependency confusion, and trojanized updates.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import hashlib
|
|
import re
|
|
import subprocess
|
|
from datetime import datetime
|
|
|
|
try:
|
|
import requests
|
|
HAS_REQUESTS = True
|
|
except ImportError:
|
|
HAS_REQUESTS = False
|
|
|
|
|
|
def compute_hash(filepath):
|
|
hashes = {}
|
|
for algo in ("md5", "sha1", "sha256"):
|
|
h = hashlib.new(algo)
|
|
with open(filepath, "rb") as f:
|
|
for chunk in iter(lambda: f.read(65536), b""):
|
|
h.update(chunk)
|
|
hashes[algo] = h.hexdigest()
|
|
return hashes
|
|
|
|
|
|
def check_npm_package(package_name):
|
|
if not HAS_REQUESTS:
|
|
return {"error": "requests not installed"}
|
|
url = f"https://registry.npmjs.org/{package_name}"
|
|
try:
|
|
resp = requests.get(url, timeout=15)
|
|
resp.raise_for_status()
|
|
data = resp.json()
|
|
latest = data.get("dist-tags", {}).get("latest", "")
|
|
versions = list(data.get("versions", {}).keys())
|
|
maintainers = data.get("maintainers", [])
|
|
return {
|
|
"name": package_name, "latest": latest,
|
|
"version_count": len(versions),
|
|
"maintainers": [m.get("name") for m in maintainers],
|
|
}
|
|
except requests.RequestException as e:
|
|
return {"error": str(e)}
|
|
|
|
|
|
def check_pypi_package(package_name):
|
|
if not HAS_REQUESTS:
|
|
return {"error": "requests not installed"}
|
|
url = f"https://pypi.org/pypi/{package_name}/json"
|
|
try:
|
|
resp = requests.get(url, timeout=15)
|
|
resp.raise_for_status()
|
|
data = resp.json()
|
|
info = data.get("info", {})
|
|
return {
|
|
"name": info.get("name"), "version": info.get("version"),
|
|
"author": info.get("author"),
|
|
"release_count": len(data.get("releases", {})),
|
|
}
|
|
except requests.RequestException as e:
|
|
return {"error": str(e)}
|
|
|
|
|
|
def detect_typosquat_packages(target_name):
|
|
permutations = set()
|
|
for i in range(len(target_name)):
|
|
permutations.add(target_name[:i] + target_name[i+1:])
|
|
for i in range(len(target_name) - 1):
|
|
swapped = list(target_name)
|
|
swapped[i], swapped[i+1] = swapped[i+1], swapped[i]
|
|
permutations.add("".join(swapped))
|
|
permutations.add(target_name.replace("-", "_"))
|
|
permutations.add(target_name.replace("_", "-"))
|
|
permutations.discard(target_name)
|
|
return sorted(permutations)
|
|
|
|
|
|
def analyze_package_scripts(package_json_path):
|
|
with open(package_json_path, "r") as f:
|
|
pkg = json.load(f)
|
|
findings = []
|
|
scripts = pkg.get("scripts", {})
|
|
for hook in ["preinstall", "postinstall", "preuninstall"]:
|
|
if hook in scripts:
|
|
cmd = scripts[hook]
|
|
findings.append({
|
|
"type": "install_hook", "hook": hook, "command": cmd[:200],
|
|
"severity": "HIGH" if any(s in cmd.lower() for s in
|
|
["curl", "wget", "eval", "exec", "base64"]) else "MEDIUM",
|
|
})
|
|
deps = {**pkg.get("dependencies", {}), **pkg.get("devDependencies", {})}
|
|
for dep, ver in deps.items():
|
|
if ver.startswith("http") or ver.startswith("git"):
|
|
findings.append({
|
|
"type": "url_dependency", "package": dep,
|
|
"source": ver[:200], "severity": "HIGH",
|
|
})
|
|
return {"name": pkg.get("name"), "findings": findings}
|
|
|
|
|
|
def analyze_python_setup(setup_py_path):
|
|
with open(setup_py_path, "r") as f:
|
|
content = f.read()
|
|
findings = []
|
|
patterns = [
|
|
(r"os\.system\(", "os.system() execution"),
|
|
(r"subprocess\.", "subprocess execution"),
|
|
(r"exec\(", "exec() code execution"),
|
|
(r"eval\(", "eval() code execution"),
|
|
(r"base64\.b64decode", "Base64 decoding"),
|
|
(r"socket\.", "Network socket usage"),
|
|
]
|
|
for pattern, description in patterns:
|
|
if re.search(pattern, content):
|
|
findings.append({
|
|
"type": "suspicious_setup_code",
|
|
"pattern": description, "severity": "HIGH",
|
|
})
|
|
return {"file": setup_py_path, "findings": findings}
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("=" * 60)
|
|
print("Supply Chain Malware Artifact Analysis Agent")
|
|
print("Package integrity, typosquat detection, install hook analysis")
|
|
print("=" * 60)
|
|
|
|
target = sys.argv[1] if len(sys.argv) > 1 else None
|
|
if not target:
|
|
print("\n[DEMO] Usage:")
|
|
print(" python agent.py <package.json> # Analyze npm package")
|
|
print(" python agent.py npm:<package_name> # Check npm registry")
|
|
print(" python agent.py pypi:<package_name> # Check PyPI registry")
|
|
sys.exit(0)
|
|
|
|
if target.startswith("npm:"):
|
|
pkg_name = target[4:]
|
|
print(f"\n[*] Checking npm: {pkg_name}")
|
|
info = check_npm_package(pkg_name)
|
|
typos = detect_typosquat_packages(pkg_name)
|
|
print(json.dumps(info, indent=2))
|
|
print(f"\n Potential typosquats: {typos[:10]}")
|
|
elif target.startswith("pypi:"):
|
|
pkg_name = target[5:]
|
|
print(f"\n[*] Checking PyPI: {pkg_name}")
|
|
info = check_pypi_package(pkg_name)
|
|
print(json.dumps(info, indent=2))
|
|
elif os.path.exists(target):
|
|
basename = os.path.basename(target)
|
|
if basename == "package.json":
|
|
result = analyze_package_scripts(target)
|
|
elif basename == "setup.py":
|
|
result = analyze_python_setup(target)
|
|
else:
|
|
result = {"file": target, "hashes": compute_hash(target)}
|
|
print(json.dumps(result, indent=2))
|