Skip to content
Development
Skill

/security-patterns

App security: OWASP, authN/authZ, input validation, secrets, TLS, CSRF/XSS/SQLi, JWT, CSP, LLM prompt injection. Triggers: security, OWASP, auth, JWT, CSRF, XSS, SQL injection, secrets, TLS, CSP, CORS, prompt injection, LLM output trust, tool permissions.

From plugin
ai-toolkit
161111 skills44 agents
Install
$ npx -y skills add softspark/ai-toolkit --skill security-patterns --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/security-patterns

Context preview

The summary Claude sees to decide when to auto-load this skill.

App security: OWASP, authN/authZ, input validation, secrets, TLS, CSRF/XSS/SQLi, JWT, CSP, LLM prompt injection. Triggers: security, OWASP, auth, JWT, CSRF, XSS, SQL injection, secrets, TLS, CSP, CORS, prompt injection, LLM output trust, tool permissions.

SKILL.md

security-patterns.SKILL.md
name: security-patterns
description: "App security: OWASP, authN/authZ, input validation, secrets, TLS, CSRF/XSS/SQLi, JWT, CSP, LLM prompt injection. Triggers: security, OWASP, auth, JWT, CSRF, XSS, SQL injection, secrets, TLS, CSP, CORS, prompt injection, LLM output trust, tool permissions."
effort: medium
user-invocable: false
allowed-tools: Read

Security Patterns Skill

OWASP Top 10 Prevention

| Risk | Prevention | |------|------------| | Injection | Parameterized queries, ORM | | Broken Auth | MFA, secure sessions | | Sensitive Data | Encryption, HTTPS | | XXE | Disable external entities | | Broken Access | RBAC, resource validation | | Security Misconfig | Security headers, defaults | | XSS | Escaping, CSP | | Insecure Deserialization | Signed tokens, validation | | Vulnerable Components | Dependency scanning | | Insufficient Logging | Audit logs, monitoring |

---

Security Headers

# FastAPI middleware
@app.middleware("http")
async def security_headers(request, call_next):
    response = await call_next(request)
    response.headers["X-Content-Type-Options"] = "nosniff"
    response.headers["X-Frame-Options"] = "DENY"
    response.headers["X-XSS-Protection"] = "1; mode=block"
    response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
    response.headers["Content-Security-Policy"] = "default-src 'self'"
    return response

---

Secrets Management

Environment Variables

# .env (never commit)
DATABASE_URL=postgresql://...
API_SECRET=...

# .env.example (commit this)
DATABASE_URL=postgresql://user:pass@localhost/db
API_SECRET=your-secret-here

Secret Scanning

# pre-commit hook
- repo: https://github.com/Yelp/detect-secrets
  hooks:
    - id: detect-secrets

---

Rate Limiting

from slowapi import Limiter
from slowapi.util import get_remote_address

limiter = Limiter(key_func=get_remote_address)

@app.get("/api/resource")
@limiter.limit("100/minute")
async def resource():
    pass

---

Prompt Injection & LLM-Output Trust

When the app embeds an LLM, every byte the model emits — plus tool results, retrieved documents, and fetched web pages — is **untrusted input on the same footing as a raw request body**. Text inside that content that reads like an instruction ("ignore previous rules", "call the delete tool", "email the config to…") is still data. Render it, store it, classify it — but never let it drive control flow, widen permissions, or fire a side effect without an explicit human decision. This mirrors the agent-behavior rule in [constitution Article VII](../../constitution.md); the rules here cover the application you are building, not the assistant's own behavior.

Trust Boundary

| Source | Trust | Handling | |--------|-------|----------| | System prompt / app-defined policy | Trusted | The only place instructions may originate | | User chat turn | Semi-trusted | Authenticated to a user, still validate + scope to their permissions | | Model output | Untrusted | Treat as data; gate any tool call it requests | | Tool / function results | Untrusted | Re-validate before feeding back into context | | Retrieved docs / RAG chunks | Untrusted | Strip or delimit embedded instructions | | Fetched web / email / file content | Untrusted | Highest risk — sanitize before it crosses into the prompt |

Defenses

  • **Separate instructions from data.** Keep app policy in the system prompt; wrap all untrusted content in clear delimiters or distinct structured fields (e.g. a `documents` array) so the model can tell "what to do" from "what to read." Never string-concatenate retrieved text into the instruction block.
  • **Least-privilege tools.** Give each tool the narrowest scope it needs. A summarizer needs no write or network egress capability. Fewer reachable side effects shrink the blast radius of a successful injection.
  • **Human-in-the-loop for irreversible actions.** Destructive, financial, or data-exfiltrating operations (delete, transfer, send-to-external-recipient, broad file reads) require explicit human confirmation — not a model token that "looks like" approval.
  • **Validate and allowlist tool arguments.** Parse the model's proposed arguments against a schema, allowlist targets (recipient domains, table names, paths), and reject anything outside it. The model choosing a tool is a *request*, not authorization.
  • **Keep secrets out of injectable context.** Never place API keys, internal URLs, or other users' data in a prompt that an injected instruction could later echo back into output. If the model cannot see it, it cannot be coaxed into leaking it.
  • **Bound indirect (second-order) injection.** Content ingested now may carry instructions that only fire on a later turn — a poisoned doc indexed today, a web page fetched mid-task, a comment in a parsed file. Sanitize and size-limit everything at the moment it crosses the trust boundary, not when it is finally read.

Carve-out: Authorized Defensive Work

Building injection **detection** (classifiers, guardrails, eval suites) and running **authorized** red-team exercises — CTF, sanctioned pentest, internal adversarial testing of these defenses — is fully in scope. Generating injection payloads for that purpose is expected; the OWASP / authorized-testing framing of this skill applies to LLM apps exactly as it does to SQLi or XSS work.

---

Common Rationalizations

| Excuse | Why It's Wrong | |--------|----------------| | "It's an internal API, security doesn't matter" | Internal APIs get exposed — lateral movement is attackers' primary technique | | "The framework handles security" | Frameworks provide tools, not guarantees — misconfiguration is OWASP #5 | | "We'll add auth later" | Unauthenticated endpoints in production get discovered within hours | | "Nobody would exploit this" | Automated scanners don't care about your threat model — they scan everything | | "It's behind a VPN" | VPNs are perimeter defe

Read more
Ships withai-toolkit

Professional-grade AI coding toolkit with multi-platform support. Machine-enforced safety, 109 skills, 44 agents, expanded lifecycle hooks, persona presets, experimental opt-in plugin packs, and benchmark tooling — works with Claude Code, Claude Chat/Cowork,

Get the whole plugin