mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-12 14:14:56 +03:00
Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills: - scripts/agent.py: 80-150 line Python agents using real libraries (impacket, boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.) - references/api-reference.md: real API documentation with method signatures - LICENSE: MIT license for all skill folders
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Anthropic Agent Skills Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,61 @@
|
||||
# API Reference: Implementing API Schema Validation Security
|
||||
|
||||
## jsonschema (Python)
|
||||
|
||||
```python
|
||||
import jsonschema
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string", "maxLength": 100},
|
||||
"email": {"type": "string", "format": "email"},
|
||||
},
|
||||
"required": ["name", "email"],
|
||||
"additionalProperties": False, # Prevent mass assignment
|
||||
}
|
||||
jsonschema.validate(instance=payload, schema=schema)
|
||||
```
|
||||
|
||||
## OpenAPI Security Checks
|
||||
|
||||
| Check | Risk | Severity |
|
||||
|-------|------|----------|
|
||||
| No request body schema | Injection | HIGH |
|
||||
| additionalProperties: true | Mass assignment | MEDIUM |
|
||||
| String without maxLength | Buffer overflow | MEDIUM |
|
||||
| No response schema | Data exposure | MEDIUM |
|
||||
| No security scheme | Broken auth | CRITICAL |
|
||||
| Security explicitly disabled | Unauthenticated access | CRITICAL |
|
||||
|
||||
## OpenAPI Schema Best Practices
|
||||
|
||||
```yaml
|
||||
components:
|
||||
schemas:
|
||||
User:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
maxLength: 100
|
||||
pattern: "^[a-zA-Z ]+$"
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
maxLength: 255
|
||||
required: [name, email]
|
||||
```
|
||||
|
||||
## Spectral (OpenAPI Linter)
|
||||
|
||||
```bash
|
||||
spectral lint openapi.yaml --ruleset .spectral.yaml
|
||||
# Custom security rules in .spectral.yaml
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- jsonschema: https://python-jsonschema.readthedocs.io/
|
||||
- OpenAPI 3.0: https://spec.openapis.org/oas/v3.0.3
|
||||
- Spectral: https://stoplight.io/open-source/spectral
|
||||
@@ -0,0 +1,169 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for auditing API schema validation security using OpenAPI specs."""
|
||||
|
||||
import json
|
||||
import argparse
|
||||
import re
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
import yaml
|
||||
except ImportError:
|
||||
yaml = None
|
||||
|
||||
try:
|
||||
import jsonschema
|
||||
except ImportError:
|
||||
jsonschema = None
|
||||
|
||||
|
||||
def load_openapi_spec(spec_path):
|
||||
"""Load an OpenAPI specification file."""
|
||||
with open(spec_path) as f:
|
||||
if spec_path.endswith((".yaml", ".yml")):
|
||||
return yaml.safe_load(f)
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def audit_schema_validation(spec):
|
||||
"""Audit OpenAPI spec for missing schema validation."""
|
||||
findings = []
|
||||
paths = spec.get("paths", {})
|
||||
for path, methods in paths.items():
|
||||
for method, details in methods.items():
|
||||
if method in ("get", "post", "put", "patch", "delete"):
|
||||
request_body = details.get("requestBody", {})
|
||||
if method in ("post", "put", "patch") and not request_body:
|
||||
findings.append({
|
||||
"path": path, "method": method.upper(),
|
||||
"issue": "no_request_body_schema", "severity": "HIGH",
|
||||
})
|
||||
elif request_body:
|
||||
content = request_body.get("content", {})
|
||||
for media, media_def in content.items():
|
||||
schema = media_def.get("schema", {})
|
||||
if not schema:
|
||||
findings.append({
|
||||
"path": path, "method": method.upper(),
|
||||
"issue": "empty_request_schema", "severity": "HIGH",
|
||||
})
|
||||
elif schema.get("additionalProperties") is not False:
|
||||
findings.append({
|
||||
"path": path, "method": method.upper(),
|
||||
"issue": "additional_properties_allowed",
|
||||
"severity": "MEDIUM",
|
||||
"risk": "mass_assignment",
|
||||
})
|
||||
params = details.get("parameters", [])
|
||||
for param in params:
|
||||
if not param.get("schema"):
|
||||
findings.append({
|
||||
"path": path, "method": method.upper(),
|
||||
"parameter": param.get("name"),
|
||||
"issue": "parameter_no_schema", "severity": "MEDIUM",
|
||||
})
|
||||
elif param.get("schema", {}).get("type") == "string":
|
||||
schema = param["schema"]
|
||||
if not schema.get("maxLength") and not schema.get("pattern"):
|
||||
findings.append({
|
||||
"path": path, "method": method.upper(),
|
||||
"parameter": param.get("name"),
|
||||
"issue": "string_no_max_length", "severity": "MEDIUM",
|
||||
"risk": "injection",
|
||||
})
|
||||
responses = details.get("responses", {})
|
||||
for code, resp in responses.items():
|
||||
content = resp.get("content", {})
|
||||
for media, media_def in content.items():
|
||||
schema = media_def.get("schema", {})
|
||||
if not schema:
|
||||
findings.append({
|
||||
"path": path, "method": method.upper(),
|
||||
"response_code": code,
|
||||
"issue": "no_response_schema", "severity": "MEDIUM",
|
||||
"risk": "data_exposure",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def check_security_definitions(spec):
|
||||
"""Check security scheme definitions in OpenAPI spec."""
|
||||
findings = []
|
||||
version = spec.get("openapi", spec.get("swagger", ""))
|
||||
if version.startswith("3"):
|
||||
security_schemes = spec.get("components", {}).get("securitySchemes", {})
|
||||
else:
|
||||
security_schemes = spec.get("securityDefinitions", {})
|
||||
if not security_schemes:
|
||||
findings.append({"issue": "no_security_schemes_defined", "severity": "CRITICAL"})
|
||||
global_security = spec.get("security", [])
|
||||
if not global_security:
|
||||
findings.append({"issue": "no_global_security", "severity": "HIGH"})
|
||||
paths = spec.get("paths", {})
|
||||
for path, methods in paths.items():
|
||||
for method, details in methods.items():
|
||||
if method in ("get", "post", "put", "patch", "delete"):
|
||||
op_security = details.get("security")
|
||||
if op_security == []:
|
||||
findings.append({
|
||||
"path": path, "method": method.upper(),
|
||||
"issue": "security_explicitly_disabled", "severity": "CRITICAL",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def validate_request_payload(schema_path, payload_path):
|
||||
"""Validate a request payload against a JSON schema."""
|
||||
if jsonschema is None:
|
||||
return {"error": "jsonschema not installed"}
|
||||
with open(schema_path) as f:
|
||||
schema = json.load(f)
|
||||
with open(payload_path) as f:
|
||||
payload = json.load(f)
|
||||
errors = []
|
||||
v = jsonschema.Draft7Validator(schema)
|
||||
for error in v.iter_errors(payload):
|
||||
errors.append({
|
||||
"path": list(error.path),
|
||||
"message": error.message,
|
||||
"schema_path": list(error.schema_path),
|
||||
})
|
||||
return {"valid": len(errors) == 0, "errors": errors}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="API Schema Validation Security Agent")
|
||||
parser.add_argument("--spec", help="OpenAPI spec file (JSON/YAML)")
|
||||
parser.add_argument("--schema", help="JSON Schema for validation")
|
||||
parser.add_argument("--payload", help="Request payload to validate")
|
||||
parser.add_argument("--output", default="schema_validation_report.json")
|
||||
parser.add_argument("--action", choices=["audit", "security", "validate", "full"],
|
||||
default="full")
|
||||
args = parser.parse_args()
|
||||
|
||||
report = {"generated_at": datetime.utcnow().isoformat(), "findings": {}}
|
||||
|
||||
if args.spec:
|
||||
spec = load_openapi_spec(args.spec)
|
||||
if args.action in ("audit", "full"):
|
||||
f = audit_schema_validation(spec)
|
||||
report["findings"]["schema_audit"] = f
|
||||
print(f"[+] Schema validation issues: {len(f)}")
|
||||
if args.action in ("security", "full"):
|
||||
f = check_security_definitions(spec)
|
||||
report["findings"]["security_schemes"] = f
|
||||
print(f"[+] Security definition issues: {len(f)}")
|
||||
|
||||
if args.action == "validate" and args.schema and args.payload:
|
||||
result = validate_request_payload(args.schema, args.payload)
|
||||
report["findings"]["validation"] = result
|
||||
print(f"[+] Validation: {'PASS' if result.get('valid') else 'FAIL'}")
|
||||
|
||||
with open(args.output, "w") as fout:
|
||||
json.dump(report, fout, indent=2, default=str)
|
||||
print(f"[+] Report saved to {args.output}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user