mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-12 14:14: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
92 lines
3.6 KiB
Python
92 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
"""FIDO2 Passwordless Auth Agent - audits FIDO2 deployment readiness and credential status."""
|
|
|
|
import json
|
|
import argparse
|
|
import logging
|
|
import subprocess
|
|
from datetime import datetime
|
|
|
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def graph_api(token, endpoint):
|
|
cmd = ["curl", "-s", "-H", f"Authorization: Bearer {token}",
|
|
f"https://graph.microsoft.com/v1.0{endpoint}"]
|
|
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
|
|
return json.loads(result.stdout) if result.stdout else {}
|
|
|
|
|
|
def get_fido2_policy(token):
|
|
return graph_api(token, "/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/fido2")
|
|
|
|
|
|
def get_registrations(token):
|
|
return graph_api(token, "/reports/authenticationMethods/userRegistrationDetails")
|
|
|
|
|
|
def audit_fido2_policy(policy):
|
|
findings = []
|
|
if policy.get("state") != "enabled":
|
|
findings.append({"issue": f"FIDO2 policy state: {policy.get('state', 'unknown')}", "severity": "high"})
|
|
if not policy.get("keyRestrictions", {}).get("aaGuids"):
|
|
findings.append({"issue": "No AAGUID restrictions set", "severity": "medium"})
|
|
if not policy.get("isAttestationEnforced"):
|
|
findings.append({"issue": "Attestation not enforced", "severity": "medium"})
|
|
return findings
|
|
|
|
|
|
def analyze_adoption(registrations):
|
|
users = registrations.get("value", [])
|
|
total = len(users)
|
|
fido2 = sum(1 for u in users if "fido2" in str(u.get("methodsRegistered", [])).lower())
|
|
passwordless = sum(1 for u in users if u.get("isPasswordlessCapable", False))
|
|
return {
|
|
"total_users": total, "fido2_registered": fido2, "passwordless_capable": passwordless,
|
|
"fido2_adoption_rate": round(fido2 / max(total, 1) * 100, 1),
|
|
}
|
|
|
|
|
|
def check_rp_config(rp_url):
|
|
cmd = ["curl", "-s", f"{rp_url}/.well-known/webauthn"]
|
|
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
|
|
findings = []
|
|
try:
|
|
config = json.loads(result.stdout)
|
|
except json.JSONDecodeError:
|
|
config = {}
|
|
findings.append({"issue": "WebAuthn well-known not configured", "severity": "high"})
|
|
return {"config": config, "findings": findings}
|
|
|
|
|
|
def generate_report(policy, policy_findings, adoption, rp):
|
|
return {
|
|
"timestamp": datetime.utcnow().isoformat(),
|
|
"fido2_policy_state": policy.get("state", "unknown"),
|
|
"policy_findings": policy_findings, "adoption_metrics": adoption,
|
|
"rp_config": rp,
|
|
"total_findings": len(policy_findings) + len(rp.get("findings", [])),
|
|
}
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="FIDO2 Passwordless Authentication Audit Agent")
|
|
parser.add_argument("--token", required=True, help="Graph API bearer token")
|
|
parser.add_argument("--rp-url", help="WebAuthn relying party URL")
|
|
parser.add_argument("--output", default="fido2_audit_report.json")
|
|
args = parser.parse_args()
|
|
policy = get_fido2_policy(args.token)
|
|
policy_findings = audit_fido2_policy(policy)
|
|
registrations = get_registrations(args.token)
|
|
adoption = analyze_adoption(registrations)
|
|
rp = check_rp_config(args.rp_url) if args.rp_url else {"config": {}, "findings": []}
|
|
report = generate_report(policy, policy_findings, adoption, rp)
|
|
with open(args.output, "w") as f:
|
|
json.dump(report, f, indent=2, default=str)
|
|
logger.info("FIDO2: adoption %.1f%%, %d findings", adoption["fido2_adoption_rate"], report["total_findings"])
|
|
print(json.dumps(report, indent=2, default=str))
|
|
|
|
if __name__ == "__main__":
|
|
main()
|