Security analysis
π Professional Multi-Agent Skills
npx -y skills add kinhluan/skills --skill security-analysisAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Security vulnerability analysis and auditing procedures. Use this skill for code security reviews, implementing DevSecOps pipelines, OWASP Top 10 mitigation, and secrets management.
SKILL.md
16.5 KB, ~4.2k tokens by cl100k_base, as published. Nobody here has run it
Security Analysis
Comprehensive security vulnerability analysis, secure code review, and DevSecOps integration. Covers OWASP Top 10 2021, automated scanning (SAST/DAST/SCA), secrets management, and threat modeling.
"Security is not a product, but a process." β Bruce Schneier
π― When to Use
- Reviewing code for security vulnerabilities before merge
- Designing secure architecture (threat modeling)
- Implementing DevSecOps CI/CD pipelines
- Conducting security audits or penetration testing preparation
- Responding to security incidents
π Core Security Principles
| Principle | Meaning | In Practice |
|---|---|---|
| Assume Breach | Design as if attacker is already inside | Defense in depth, least privilege |
| Least Privilege | Minimum permissions necessary | RBAC, service accounts, no root |
| Fail Securely | Errors don't expose sensitive data | Generic error messages, no stack traces in prod |
| Defense in Depth | Multiple independent controls | WAF + input validation + parameterized queries |
| Zero Trust | Never trust, always verify | MFA, mTLS, continuous validation |
| Shift Left | Security as early as possible | SAST in IDE, pre-commit hooks |
π‘οΈ OWASP Top 10 2021
A01: Broken Access Control
What: Users can access resources they shouldn't.
Vulnerable Code:
# VULNERABLE: No authorization check
@app.get("/api/orders/{order_id}")
def get_order(order_id: str):
return db.query(f"SELECT * FROM orders WHERE id = '{order_id}'")
# VULNERABLE: Client-controlled user ID
@app.get("/api/orders")
def get_orders(user_id: str = Query(...)): # attacker changes user_id
return db.query(f"SELECT * FROM orders WHERE user_id = '{user_id}'")
Secure Code:
from fastapi import Depends, HTTPException
@app.get("/api/orders/{order_id}")
def get_order(
order_id: str,
current_user: User = Depends(get_current_user)
):
order = db.get_order(order_id)
# Authorize: user can only access their own orders
if order.user_id != current_user.id and not current_user.is_admin:
raise HTTPException(status_code=403, detail="Access denied")
return order
Checklist:
- Deny by default β allowlist, not blocklist
- Access control enforced server-side, never client-side
- CORS configured correctly (not
*in production) - Rate limiting on auth endpoints
- Admin functions on separate route/API
A02: Cryptographic Failures
What: Sensitive data exposed due to weak or missing cryptography.
Vulnerable Code:
# VULNERABLE: MD5 for passwords
import hashlib
password_hash = hashlib.md5(password.encode()).hexdigest()
# VULNERABLE: Hardcoded key
SECRET_KEY = "my-secret-key-123"
Secure Code:
# Python: bcrypt for passwords
import bcrypt
# Hash
password_hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))
# Verify
bcrypt.checkpw(password.encode(), password_hash)
# AES-GCM encryption
from cryptography.fernet import Fernet
key = Fernet.generate_key() # Store in vault, not code!
cipher = Fernet(key)
token = cipher.encrypt(b"sensitive data")
// Go: bcrypt + argon2
import "golang.org/x/crypto/bcrypt"
// Hash
hash, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
// Verify
bcrypt.CompareHashAndPassword(hash, []byte(password))
Checklist:
- Passwords: bcrypt/argon2/scrypt (NOT MD5/SHA1)
- Data at rest: AES-256-GCM
- Data in transit: TLS 1.3 (disable TLS 1.0/1.1)
- Keys: stored in vault (HashiCorp Vault, AWS KMS, etc.)
- No hardcoded secrets (use environment variables + vault)
A03: Injection
What: Untrusted data sent to interpreter (SQL, NoSQL, OS, LDAP).
Vulnerable Code:
# VULNERABLE: SQL Injection
query = f"SELECT * FROM users WHERE id = '{user_id}'"
cursor.execute(query)
# VULNERABLE: Command Injection
import os
os.system(f"convert {user_input} output.png")
Secure Code:
# SECURE: Parameterized query
query = "SELECT * FROM users WHERE id = %s"
cursor.execute(query, (user_id,))
# SECURE: ORM (Django/SQLAlchemy)
User.objects.filter(id=user_id) # automatically parameterized
# SECURE: No shell execution
import subprocess
subprocess.run(["convert", user_input, "output.png"], check=True)
# List form prevents shell injection
// SECURE: Go database/sql
db.Query("SELECT * FROM users WHERE id = ?", userID)
// SECURE: Go with squirrel query builder
squirrel.Select("*").From("users").Where(squirrel.Eq{"id": userID})
Checklist:
- All queries parameterized (prepared statements)
- ORM used where possible
- No dynamic table/column names from user input
- Shell commands avoided; if necessary, use array form
- Input validation with allowlists
A04: Insecure Design
What: Missing or ineffective security controls in design.
Examples:
- No rate limiting on password reset
- Business logic flaws (e.g., negative quantity in cart)
- Missing anti-CSRF tokens
- Insecure direct object references (IDOR)
Secure Design Patterns:
# Rate limiting
from slowapi import Limiter
limiter = Limiter(key_func=lambda: request.client.host)
@app.post("/login")
@limiter.limit("5/minute")
def login(credentials: LoginRequest):
...
# Business logic validation
class OrderItem(BaseModel):
product_id: str
quantity: int
@validator('quantity')
def quantity_positive(cls, v):
if v <= 0:
raise ValueError('Quantity must be positive')
return v
# Anti-CSRF
def validate_csrf_token(request):
token = request.headers.get('X-CSRF-Token')
if not hmac.compare_digest(token, get_expected_token(request)):
raise HTTPException(403, "Invalid CSRF token")
A05: Security Misconfiguration
What: Default configs, verbose errors, unnecessary features enabled.
Common Issues:
# VULNERABLE: Debug mode in production
app = FastAPI(debug=True) # Exposes stack traces!
# VULNERABLE: CORS allows everything
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Dangerous!
allow_credentials=True,
)
# VULNERABLE: Verbose error messages
@app.exception_handler(Exception)
def handle_error(request, exc):
return JSONResponse(
status_code=500,
content={"error": str(exc), "traceback": traceback.format_exc()} # Leaks internals!
)
Secure Configuration:
# Production config
app = FastAPI(debug=False) # Never True in production
# Restricted CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["https://app.example.com"], # Explicit allowlist
allow_credentials=True,
allow_methods=["GET", "POST"],
allow_headers=["Authorization", "Content-Type"],
)
# Generic error messages
@app.exception_handler(Exception)
def handle_error(request, exc):
logger.error(f"Unhandled error: {exc}", exc_info=True) # Log internally
return JSONResponse(
status_code=500,
content={"error": "Internal server error", "request_id": request.state.request_id}
)
Security Headers (all responses):
# Add via middleware or reverse proxy
headers = {
"Content-Security-Policy": "default-src 'self'",
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"X-XSS-Protection": "1; mode=block",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains",
"Referrer-Policy": "strict-origin-when-cross-origin",
}
A06: Vulnerable and Outdated Components
What: Using dependencies with known CVEs.
Detection & Mitigation:
# Python
pip install safety
safety check # Scan requirements.txt
# Node.js
npm audit
npm audit fix
# Go
go list -json -m all | nancy sleuth
# Docker image scanning
trivy image myapp:latest
# GitHub Dependabot (automated)
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "daily"
A07: Identification and Authentication Failures
What: Weak auth mechanisms, session management flaws.
Secure Implementation:
# JWT with proper config
from jose import jwt
token = jwt.encode(
{"sub": user_id, "iat": now, "exp": now + 3600},
secret_key,
algorithm="HS256" # Use RS256 for asymmetric
)
# Session management
@app.post("/logout")
def logout(response: Response):
response.delete_cookie("session_id")
invalidate_session(session_id)
# MFA (TOTP)
import pyotp
totp = pyotp.TOTP(user.mfa_secret)
assert totp.verify(code) # 6-digit code from authenticator app
Checklist:
- Strong password policy (NIST 800-63b)
- MFA enabled for sensitive accounts
- Session timeout (idle: 15min, absolute: 8h)
- Secure session cookies (HttpOnly, Secure, SameSite)
- Account lockout after failed attempts
A08: Software and Data Integrity Failures
What: Insecure deserialization, untrusted dependencies, CI/CD tampering.
Prevention:
# Never deserialize untrusted data with pickle!
# VULNERABLE:
# data = pickle.loads(untrusted_data) # RCE!
# SECURE: Use JSON
import json
data = json.loads(untrusted_data)
# Verify software signatures
import gpg
verified = gpg.verify_file(signature_file, data_file)
assert verified.valid
# CI/CD: Signed commits
# Require signed commits in GitHub branch protection
# Use SLSA provenance for build artifacts
A09: Security Logging and Monitoring Failures
What: Insufficient logging allows attacks to go undetected.
What to Log:
# Security events (always log)
- Login attempts (success and failure)
- Privilege escalation
- Data access (sensitive resources)
- Configuration changes
- Authentication failures
# What NOT to log
- Passwords
- API keys
- PII (unless necessary, then masked)
- Session tokens
Structured Logging:
import structlog
logger = structlog.get_logger()
# Good security log
logger.info(
"login_attempt",
user_id=user_id,
ip_address=request.client.host,
success=False,
reason="invalid_password",
user_agent=request.headers.get("user-agent"),
)
# Alert on anomalies
# - >5 failed logins from same IP in 1 minute
# - Access from unusual geolocation
# - Privilege escalation outside business hours
A10: Server-Side Request Forgery (SSRF)
What: Server makes requests to attacker-controlled URLs.
Vulnerable Code:
# VULNERABLE: User controls URL
url = request.json["webhook_url"]
response = requests.get(url) # Can access internal services!
Secure Code:
import urllib.parse
def validate_url(url: str) -> bool:
parsed = urllib.parse.urlparse(url)
# Block internal IPs, localhost, file://
blocked_hosts = {"localhost", "127.0.0.1", "0.0.0.0", "::1"}
if parsed.hostname in blocked_hosts:
return False
# Resolve and check IP isn't private
ip = socket.gethostbyname(parsed.hostname)
if ipaddress.ip_address(ip).is_private:
return False
return parsed.scheme in {"http", "https"}
if not validate_url(url):
raise HTTPException(400, "Invalid URL")
response = requests.get(url, timeout=5)
π¬ DevSecOps: Automated Security Testing
SAST (Static Application Security Testing)
# .github/workflows/security.yml
name: Security Scan
on: [pull_request]
jobs:
sast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Python
- name: Bandit (Python SAST)
run: |
pip install bandit
bandit -r src/ -f json -o bandit-report.json || true
# JavaScript/TypeScript
- name: ESLint Security
run: |
npm install eslint-plugin-security
npx eslint . --ext .js,.ts
# Go
- name: Gosec (Go SAST)
run: |
go install github.com/securego/gosec/v2/cmd/gosec@latest
gosec ./...
# Multi-language
- name: Semgrep
run: |
pip install semgrep
semgrep --config=auto --json --output=semgrep.json src/
DAST (Dynamic Application Security Testing)
dast:
runs-on: ubuntu-latest
needs: deploy-staging
steps:
- name: OWASP ZAP Scan
uses: zaproxy/[email protected]
with:
target: 'https://staging.example.com'
rules_file_name: '.zap/rules.tsv'
SCA (Software Composition Analysis)
sca:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload to GitHub Security tab
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
Secrets Scanning
secrets:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history for trufflehog
- name: TruffleHog
uses: trufflesecurity/trufflehog@main
with:
path: ./
base: main
head: HEAD
π Secrets Management
Never Do This
# β HARDCODED SECRETS
API_KEY = "sk-live-abc123"
DATABASE_URL = "postgres://admin:password@db:5432/app"
Do This Instead
# β
Environment variables
import os
API_KEY = os.environ["API_KEY"]
# β
Secrets manager (AWS)
import boto3
client = boto3.client('secretsmanager')
secret = client.get_secret_value(SecretId="prod/api-key")
# β
HashiCorp Vault
import hvac
client = hvac.Client(url='https://vault.example.com')
client.token = os.environ['VAULT_TOKEN']
secret = client.secrets.kv.v2.read_secret_version(path='api-key')
# β
Kubernetes secrets
# Mount as file, not env var (prevents /proc exposure)
with open('/var/run/secrets/api-key') as f:
api_key = f.read().strip()
Pre-commit Hook (prevent secrets in git)
# .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
hooks:
- id: detect-private-key
- repo: https://github.com/Yelp/detect-secrets
hooks:
- id: detect-secrets
args: ['--baseline', '.secrets.baseline']
- repo: https://github.com/trufflesecurity/trufflehog
hooks:
- id: trufflehog
args: ["filesystem", "--only-verified", "."]
π― Secure Code Review Checklist
Input Validation
- All user input validated (type, length, format, range)
- Allowlist validation preferred over blocklist
- File uploads: validate type, size, scan for malware
- URL parameters: no sensitive data exposed
Authentication & Authorization
- Auth checks on every protected endpoint
- Principle of least privilege enforced
- Session management secure (timeout, invalidation)
- No sensitive operations without re-authentication
Data Protection
- Passwords hashed with bcrypt/argon2
- Sensitive data encrypted at rest (AES-256)
- TLS 1.3 for all communications
- PII masked in logs
Output Encoding
- HTML output escaped (prevent XSS)
- JSON properly serialized
- Content-Type headers set correctly
- Download filenames sanitized
Error Handling
- Generic error messages to users
- Detailed errors logged internally
- No stack traces in production responses
- Fail securely (deny access on error)
Dependencies
- No known CVEs in dependencies
- Dependencies pinned (lock files)
- Minimal dependencies principle
- Regular dependency updates
π Severity Assessment
| Severity | CVSS | Example | Response Time |
|---|---|---|---|
| Critical | 9.0-10.0 | RCE, SQLi with data exfiltration | 24 hours |
| High | 7.0-8.9 | Auth bypass, IDOR on sensitive data | 72 hours |
| Medium | 4.0-6.9 | XSS, CSRF, information disclosure | 1 week |
| Low | 0.1-3.9 | Verbose errors, missing headers | 1 month |
π References
What ships with it: 1 file
1.9 KB alongside SKILL.md
- SKILL.toon1.9 KB