mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-08-11 04:43:19 +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,72 @@
|
||||
# API Reference: Serverless Function Security Review
|
||||
|
||||
## Overview
|
||||
|
||||
Agent automates Lambda security reviews using boto3 to audit execution roles, environment variable secrets, deprecated runtimes, and public access configurations.
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Package | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| boto3 | >= 1.28 | AWS SDK for Lambda and IAM API calls |
|
||||
| botocore | >= 1.31 | Exception handling for AWS API errors |
|
||||
|
||||
## Core Functions
|
||||
|
||||
### `list_all_functions(client)`
|
||||
Paginates through all Lambda functions in the region.
|
||||
- **Parameters**: `client` - boto3 Lambda client
|
||||
- **Returns**: `list[dict]` - full function configuration objects
|
||||
|
||||
### `check_deprecated_runtime(runtime)`
|
||||
Checks if a Lambda runtime is end-of-life.
|
||||
- **Parameters**: `runtime` (str) - Lambda runtime identifier
|
||||
- **Returns**: `bool` - True if deprecated
|
||||
|
||||
### `audit_execution_role(iam, role_arn)`
|
||||
Inspects attached IAM policies for wildcard actions and AdministratorAccess.
|
||||
- **Parameters**: `iam` - boto3 IAM client, `role_arn` (str)
|
||||
- **Returns**: `list[str]` - finding descriptions
|
||||
|
||||
### `check_env_secrets(env_vars)`
|
||||
Scans environment variables for sensitive patterns (passwords, API keys, AWS credentials).
|
||||
- **Parameters**: `env_vars` (dict) - Lambda environment variables
|
||||
- **Returns**: `list[str]` - masked sensitive variable findings
|
||||
|
||||
### `check_public_access(client, function_name)`
|
||||
Checks resource-based policies and function URLs for unauthenticated access.
|
||||
- **Parameters**: `client` - boto3 Lambda client, `function_name` (str)
|
||||
- **Returns**: `list[str]` - public access findings
|
||||
|
||||
### `run_review(region="us-east-1")`
|
||||
Orchestrates the full review across all functions. Returns structured report dict.
|
||||
|
||||
## AWS API Calls Used
|
||||
|
||||
| API Call | Service | Purpose |
|
||||
|----------|---------|---------|
|
||||
| `list_functions` | Lambda | Enumerate all Lambda functions |
|
||||
| `get_policy` | Lambda | Retrieve resource-based policy |
|
||||
| `list_function_url_configs` | Lambda | Check function URL auth type |
|
||||
| `list_attached_role_policies` | IAM | Get policies on execution role |
|
||||
| `get_policy_version` | IAM | Read policy document for wildcards |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `AWS_ACCESS_KEY_ID` | Yes | AWS credential (or use IAM role) |
|
||||
| `AWS_SECRET_ACCESS_KEY` | Yes | AWS credential (or use IAM role) |
|
||||
| `AWS_DEFAULT_REGION` | No | Defaults to us-east-1 |
|
||||
|
||||
## Output Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"total_functions": 34,
|
||||
"deprecated_runtimes": [{"function": "name", "runtime": "python3.7"}],
|
||||
"role_findings": ["CRITICAL: Role X has AdministratorAccess"],
|
||||
"secret_findings": [{"function": "name", "finding": "SENSITIVE: DB_PASSWORD = prod****word"}],
|
||||
"public_access_findings": ["PUBLIC ACCESS: func allows public invocation"]
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,153 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Serverless function security review agent using boto3."""
|
||||
|
||||
import json
|
||||
import re
|
||||
import boto3
|
||||
from botocore.exceptions import ClientError
|
||||
|
||||
|
||||
def get_lambda_client(region="us-east-1"):
|
||||
return boto3.client("lambda", region_name=region)
|
||||
|
||||
|
||||
def get_iam_client(region="us-east-1"):
|
||||
return boto3.client("iam", region_name=region)
|
||||
|
||||
|
||||
def list_all_functions(client):
|
||||
functions = []
|
||||
paginator = client.get_paginator("list_functions")
|
||||
for page in paginator.paginate():
|
||||
functions.extend(page["Functions"])
|
||||
return functions
|
||||
|
||||
|
||||
def check_deprecated_runtime(runtime):
|
||||
deprecated = [
|
||||
"python2.7", "python3.6", "python3.7", "nodejs10.x",
|
||||
"nodejs12.x", "nodejs14.x", "dotnetcore2.1", "dotnetcore3.1",
|
||||
"ruby2.5", "java8", "go1.x",
|
||||
]
|
||||
return runtime in deprecated
|
||||
|
||||
|
||||
def audit_execution_role(iam, role_arn):
|
||||
findings = []
|
||||
role_name = role_arn.split("/")[-1]
|
||||
try:
|
||||
attached = iam.list_attached_role_policies(RoleName=role_name)
|
||||
for policy in attached["AttachedPolicies"]:
|
||||
if policy["PolicyName"] == "AdministratorAccess":
|
||||
findings.append(f"CRITICAL: Role {role_name} has AdministratorAccess")
|
||||
version_id = iam.get_policy(PolicyArn=policy["PolicyArn"])["Policy"]["DefaultVersionId"]
|
||||
doc = iam.get_policy_version(
|
||||
PolicyArn=policy["PolicyArn"], VersionId=version_id
|
||||
)["PolicyVersion"]["Document"]
|
||||
for stmt in doc.get("Statement", []):
|
||||
actions = stmt.get("Action", [])
|
||||
if isinstance(actions, str):
|
||||
actions = [actions]
|
||||
if "*" in actions or any(a.endswith(":*") for a in actions):
|
||||
findings.append(
|
||||
f"WARNING: {role_name} has wildcard action: {actions} "
|
||||
f"on {stmt.get('Resource', '*')}"
|
||||
)
|
||||
except ClientError as e:
|
||||
findings.append(f"ERROR auditing role {role_name}: {e}")
|
||||
return findings
|
||||
|
||||
|
||||
SENSITIVE_PATTERNS = [
|
||||
re.compile(r"(?i)(password|secret|key|token|credential|api.?key)"),
|
||||
re.compile(r"(?i)(aws.?access|aws.?secret)"),
|
||||
re.compile(r"(?i)(database.?url|connection.?string|db.?pass)"),
|
||||
re.compile(r"AKIA[0-9A-Z]{16}"),
|
||||
]
|
||||
|
||||
|
||||
def check_env_secrets(env_vars):
|
||||
findings = []
|
||||
if not env_vars:
|
||||
return findings
|
||||
for key, value in env_vars.items():
|
||||
for pattern in SENSITIVE_PATTERNS:
|
||||
if pattern.search(key) or pattern.search(str(value)):
|
||||
masked = value[:4] + "****" + value[-4:] if len(value) > 8 else "****"
|
||||
findings.append(f"SENSITIVE: {key} = {masked}")
|
||||
break
|
||||
return findings
|
||||
|
||||
|
||||
def check_public_access(client, function_name):
|
||||
findings = []
|
||||
try:
|
||||
policy = client.get_policy(FunctionName=function_name)
|
||||
doc = json.loads(policy["Policy"])
|
||||
for stmt in doc.get("Statement", []):
|
||||
principal = stmt.get("Principal", {})
|
||||
if principal == "*" or principal == {"AWS": "*"}:
|
||||
findings.append(
|
||||
f"PUBLIC ACCESS: {function_name} allows public invocation "
|
||||
f"(statement: {stmt.get('Sid', 'unnamed')})"
|
||||
)
|
||||
except ClientError:
|
||||
pass
|
||||
try:
|
||||
urls = client.list_function_url_configs(FunctionName=function_name)
|
||||
for url_cfg in urls.get("FunctionUrlConfigs", []):
|
||||
if url_cfg.get("AuthType") == "NONE":
|
||||
findings.append(
|
||||
f"UNAUTHENTICATED URL: {function_name} -> {url_cfg['FunctionUrl']}"
|
||||
)
|
||||
except ClientError:
|
||||
pass
|
||||
return findings
|
||||
|
||||
|
||||
def run_review(region="us-east-1"):
|
||||
lam = get_lambda_client(region)
|
||||
iam = get_iam_client(region)
|
||||
functions = list_all_functions(lam)
|
||||
report = {
|
||||
"total_functions": len(functions),
|
||||
"deprecated_runtimes": [],
|
||||
"role_findings": [],
|
||||
"secret_findings": [],
|
||||
"public_access_findings": [],
|
||||
}
|
||||
for func in functions:
|
||||
name = func["FunctionName"]
|
||||
runtime = func.get("Runtime", "unknown")
|
||||
if check_deprecated_runtime(runtime):
|
||||
report["deprecated_runtimes"].append({"function": name, "runtime": runtime})
|
||||
report["role_findings"].extend(audit_execution_role(iam, func["Role"]))
|
||||
env = func.get("Environment", {}).get("Variables", {})
|
||||
secrets = check_env_secrets(env)
|
||||
if secrets:
|
||||
report["secret_findings"].extend(
|
||||
[{"function": name, "finding": s} for s in secrets]
|
||||
)
|
||||
report["public_access_findings"].extend(check_public_access(lam, name))
|
||||
return report
|
||||
|
||||
|
||||
def print_report(report):
|
||||
print("Serverless Function Security Review")
|
||||
print("=" * 40)
|
||||
print(f"Functions Reviewed: {report['total_functions']}")
|
||||
for section, label in [
|
||||
("deprecated_runtimes", "Deprecated Runtimes"),
|
||||
("role_findings", "Role Issues"),
|
||||
("secret_findings", "Secrets in Env Vars"),
|
||||
("public_access_findings", "Public Access"),
|
||||
]:
|
||||
items = report[section]
|
||||
print(f"\n{label}: {len(items)} finding(s)")
|
||||
for item in items:
|
||||
print(f" - {item}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
result = run_review()
|
||||
print_report(result)
|
||||
Reference in New Issue
Block a user