mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-26 11:44:37 +03:00
8cae0648ec
Demand-driven expansion targeting the fastest-growing 2025-2026 threat and
skills categories (ISC2/WEF/CrowdStrike/Mandiant signals):
- AI Security (NEW domain, 12 skills): LLM red-teaming with garak/PyRIT,
prompt injection (direct/indirect/RAG), MCP tool-poisoning, agentic tool
invocation, guardrails, model/data poisoning, system-prompt leakage,
embedding/vector weaknesses, model extraction, continuous red-teaming
- Supply Chain Security (NEW domain, 5 skills): SBOMs, dependency confusion,
malicious-npm triage, typosquatting, SLSA/Sigstore provenance
- Hardware & Firmware Security (NEW domain, 4 skills): CHIPSEC/UEFI audit,
Secure Boot bypass, TPM measured-boot attestation, ESP bootkit hunting
- Identity (10): Entra ID/ROADtools, GraphRunner, AADInternals, ADCS/Certipy,
shadow credentials, coercion, BloodHound CE, device-code phishing, SSO abuse
- Cloud-native (8): Stratus, Pacu, CloudFox, container escape, K8s RBAC,
Falco, Trivy, kube-bench
- Offensive C2 (6): Sliver, Havoc, NetExec, DPAPI, NTLM relay ESC8, redirectors
- DFIR (6): Hayabusa, Chainsaw, KAPE, Velociraptor, EZ Tools, Plaso
- Backfill (4): OpenCTI, MISP, honeytokens, post-quantum crypto migration
Each skill follows the repo taxonomy (SKILL.md + references/{standards,api-reference}.md
+ scripts/agent.py + LICENSE), with researched real tool commands (no placeholders),
complete frontmatter, and ATT&CK/ATLAS + NIST CSF mappings. Updates README domain
table, skill count, and index.json.
160 lines
5.3 KiB
Python
160 lines
5.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
SBOM generation + vulnerability correlation helper.
|
|
|
|
Wraps Syft (SBOM generation), Grype (vulnerability scanning), and Cosign
|
|
(attestation) with real flags. Can run the full pipeline (generate -> scan ->
|
|
optionally attest) and summarize Grype JSON by severity for CI gating.
|
|
|
|
References:
|
|
https://github.com/anchore/syft
|
|
https://github.com/anchore/grype
|
|
https://github.com/sigstore/cosign
|
|
"""
|
|
import argparse
|
|
import json
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from collections import Counter
|
|
|
|
SEVERITY_ORDER = ["negligible", "low", "medium", "high", "critical"]
|
|
|
|
|
|
def require(tool):
|
|
path = shutil.which(tool)
|
|
if not path:
|
|
print(f"[!] '{tool}' not found on PATH", file=sys.stderr)
|
|
return path
|
|
|
|
|
|
def run(cmd, dry_run, capture=False):
|
|
print("[*] " + " ".join(cmd), file=sys.stderr)
|
|
if dry_run:
|
|
return 0, ""
|
|
try:
|
|
if capture:
|
|
proc = subprocess.run(cmd, check=False, text=True, capture_output=True)
|
|
if proc.returncode != 0 and proc.stderr:
|
|
print(proc.stderr, file=sys.stderr)
|
|
return proc.returncode, proc.stdout
|
|
return subprocess.run(cmd, check=False).returncode, ""
|
|
except FileNotFoundError:
|
|
print(f"[!] command not found: {cmd[0]}", file=sys.stderr)
|
|
return 127, ""
|
|
|
|
|
|
def syft_generate(source, fmt, outfile, dry_run):
|
|
syft = require("syft") or "syft"
|
|
cmd = [syft, source, "-o", f"{fmt}={outfile}"]
|
|
rc, _ = run(cmd, dry_run)
|
|
return rc
|
|
|
|
|
|
def grype_scan(sbom_path, out_json, fail_on=None, only_fixed=False, dry_run=False):
|
|
grype = require("grype") or "grype"
|
|
cmd = [grype, f"sbom:{sbom_path}", "-o", "json"]
|
|
if only_fixed:
|
|
cmd.append("--only-fixed")
|
|
if fail_on:
|
|
cmd += ["--fail-on", fail_on]
|
|
rc, out = run(cmd, dry_run, capture=True)
|
|
if out and not dry_run:
|
|
with open(out_json, "w", encoding="utf-8") as fh:
|
|
fh.write(out)
|
|
return rc, out
|
|
|
|
|
|
def summarize(grype_json_text):
|
|
"""Count vulnerabilities by severity from Grype JSON output."""
|
|
try:
|
|
data = json.loads(grype_json_text)
|
|
except (json.JSONDecodeError, TypeError):
|
|
print("[!] could not parse Grype JSON", file=sys.stderr)
|
|
return Counter()
|
|
counts = Counter()
|
|
for match in data.get("matches", []):
|
|
sev = (match.get("vulnerability", {})
|
|
.get("severity", "Unknown")).lower()
|
|
counts[sev] += 1
|
|
return counts
|
|
|
|
|
|
def print_summary(counts):
|
|
total = sum(counts.values())
|
|
print(f"[+] Total vulnerabilities: {total}")
|
|
for sev in reversed(SEVERITY_ORDER):
|
|
if counts.get(sev):
|
|
print(f" {sev:>10}: {counts[sev]}")
|
|
for sev, n in counts.items():
|
|
if sev not in SEVERITY_ORDER:
|
|
print(f" {sev:>10}: {n}")
|
|
|
|
|
|
def cosign_attest(image, predicate, attest_type, key, dry_run):
|
|
cosign = require("cosign") or "cosign"
|
|
cmd = [cosign, "attest", "--predicate", predicate, "--type", attest_type, image]
|
|
if key:
|
|
cmd[2:2] = ["--key", key] # insert after 'attest'
|
|
rc, _ = run(cmd, dry_run)
|
|
return rc
|
|
|
|
|
|
def main():
|
|
p = argparse.ArgumentParser(description="SBOM generate/scan/attest helper")
|
|
p.add_argument("--dry-run", action="store_true")
|
|
sub = p.add_subparsers(dest="cmd", required=True)
|
|
|
|
g = sub.add_parser("generate", help="Generate an SBOM with Syft")
|
|
g.add_argument("--source", required=True, help="image, dir:., file:..., etc.")
|
|
g.add_argument("--format", default="cyclonedx-json")
|
|
g.add_argument("--out", required=True)
|
|
|
|
s = sub.add_parser("scan", help="Scan an SBOM with Grype")
|
|
s.add_argument("--sbom", required=True)
|
|
s.add_argument("--out", default="vulns.json")
|
|
s.add_argument("--fail-on")
|
|
s.add_argument("--only-fixed", action="store_true")
|
|
|
|
pl = sub.add_parser("pipeline", help="generate -> scan -> summarize (+attest)")
|
|
pl.add_argument("--source", required=True)
|
|
pl.add_argument("--format", default="cyclonedx-json")
|
|
pl.add_argument("--sbom-out", default="sbom.json")
|
|
pl.add_argument("--vulns-out", default="vulns.json")
|
|
pl.add_argument("--fail-on")
|
|
pl.add_argument("--only-fixed", action="store_true")
|
|
pl.add_argument("--attest-image", help="If set, attest the SBOM to this image")
|
|
pl.add_argument("--attest-type", default="cyclonedx")
|
|
pl.add_argument("--cosign-key")
|
|
|
|
args = p.parse_args()
|
|
|
|
if args.cmd == "generate":
|
|
return syft_generate(args.source, args.format, args.out, args.dry_run)
|
|
|
|
if args.cmd == "scan":
|
|
rc, out = grype_scan(args.sbom, args.out, args.fail_on,
|
|
args.only_fixed, args.dry_run)
|
|
if out:
|
|
print_summary(summarize(out))
|
|
return rc
|
|
|
|
if args.cmd == "pipeline":
|
|
rc = syft_generate(args.source, args.format, args.sbom_out, args.dry_run)
|
|
if rc not in (0,) and not args.dry_run:
|
|
print("[!] SBOM generation failed", file=sys.stderr)
|
|
return rc
|
|
scan_rc, out = grype_scan(args.sbom_out, args.vulns_out, args.fail_on,
|
|
args.only_fixed, args.dry_run)
|
|
if out:
|
|
print_summary(summarize(out))
|
|
if args.attest_image:
|
|
cosign_attest(args.attest_image, args.sbom_out, args.attest_type,
|
|
args.cosign_key, args.dry_run)
|
|
return scan_rc
|
|
return 2
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|