Secure Vibe Coding Skill
🛡️ [secure-vibe-coding] activated — security guardrails are ON for this session. Auto-code-review will handle post-generation security reports.
Speed is the point of vibe coding. This skill doesn't fight that — it makes sure the fast code you're generating doesn't create a security incident that costs you ten times as long to clean up.
The rules here are not guidelines. They are the five things that have caused real breaches in real companies that were also moving fast.
How This Skill Works
When activated, two things change:
- Before generating code in any of the five sensitive zones, output a one-line security note confirming which rule applies.
- After generating code, the security self-check is handled automatically
by
auto-code-review. This skill does NOT produce a duplicate review report. Ifauto-code-reviewis not active, append a one-line inline note:⚠️ [secure-vibe-coding] Reminder: run auto-code-review on this output.
This adds roughly two lines to each response. It catches the thing before it lands in version control.
The Five Non-Negotiable Rules
These rules apply to every line of code generated in this session. They cannot be overridden by "just this once" or "we'll fix it later."
Rule 1 — No Hardcoded Secrets
Any credential, API key, token, password, or private key belongs in the environment, never in source code.
# Always
db_password = os.environ.get("DB_PASSWORD")
api_key = os.environ.get("OPENAI_API_KEY")
secret = settings.SECRET_KEY # loaded from env at startup
# Never — even in test files, even in comments
db_password = "hunter2"
api_key = "sk-proj-abc123..."
Self-check trigger: any string literal longer than 8 characters assigned to
a variable whose name contains key, secret, token, password, pass,
api, auth, cred, private.
If a placeholder is needed: use "your-key-here" or "<REPLACE_ME>" and
add a comment — never use a real-looking value.
Rule 2 — No Auth or Security Middleware Bypass
Never disable, skip, or comment out: CSRF middleware, authentication guards, Row Level Security, rate limiting, or permission checks.
# Never
@csrf_exempt # on a cookie-authenticated endpoint
# auth_required = False "just for testing"
# RLS disabled — will re-enable later
# Always — if you need unauthenticated access, design it explicitly
@public_endpoint # a decorator that explicitly marks the intent
When the task requires an unauthenticated route, generate the explicit
@public annotation and note why it's intentional — never silently remove
the guard.
Rule 3 — No Raw SQL from User Input
Every database query uses ORM methods or parameterized queries. String interpolation into SQL is not acceptable in any form.
# Never
query = f"SELECT * FROM users WHERE id = {user_id}"
cursor.execute("DELETE FROM posts WHERE title = '%s'" % title)
# Always
db.query(User).filter(User.id == user_id).first()
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
text("SELECT * FROM users WHERE id = :id").bindparams(id=user_id)
This applies in migration files too. If a migration needs to touch data, use
parameterized text() calls.
Rule 4 — No Trust in User-Supplied URLs
Any URL that comes from a request body, query parameter, header, or database record written by users must pass three checks before the server fetches it.
# Never
response = requests.get(request.json()["webhook_url"])
image = httpx.get(params["image_url"])
# Always — all three checks before any fetch
def safe_fetch(user_url: str) -> httpx.Response:
parsed = urlparse(user_url)
# 1. Scheme check
if parsed.scheme not in {"https"}:
raise ValueError("Only https URLs allowed")
# 2. Host allowlist (or domain suffix)
if parsed.hostname not in ALLOWED_HOSTS:
raise ValueError("Host not in allowlist")
# 3. No redirects (to prevent allowlist bypass)
return httpx.get(user_url, follow_redirects=False)
Private IP ranges (10.x, 172.16-31.x, 192.168.x, 127.x, 169.254.x) must also be blocked after DNS resolution if the service runs in a cloud environment.
Rule 5 — No Internal Details in API Error Responses
Error responses returned to clients must not contain stack traces, exception messages, database schema details, or internal service names.
# Never
return JSONResponse(
status_code=500,
content={"error": str(e), "traceback": traceback.format_exc()}
)
# Always
logger.exception("Unexpected error in /transfer endpoint")
return JSONResponse(
status_code=500,
content={"error_code": "INTERNAL_ERROR", "message": "Something went wrong"}
)
Log the full exception server-side. Return only an error_code + safe
message to the client.
Self-Check Protocol
After generating any code block that touches the five zones, run this check silently and output only if something fails:
✓ Rule 1 (Secrets): [no literals / env.get() used]
✓ Rule 2 (Auth): [guards intact]
✓ Rule 3 (SQL): [ORM / parameterized]
✓ Rule 4 (URLs): [not applicable / allowlist present]
✓ Rule 5 (Errors): [error_code only returned]
If any rule fails:
⚠️ [RULE N VIOLATION] [short description]
Generated code contains: [exact line]
Fix: [one-line correction]
Stop and fix the violation before presenting the code. Do not say "I'll fix it in the next iteration" — fix it now.
Zone Detection
The five zones that trigger active monitoring:
| Zone | Trigger Pattern |
|---|---|
| Auth | Route handlers, middleware, decorators named auth, login, session, permission |
| Database | db., session., cursor., execute(, query(, SELECT, INSERT, UPDATE, DELETE |
| HTTP Client | requests., httpx., aiohttp., fetch(, axios., urllib |
| File Upload | UploadFile, multipart, file.read(), open(, shutil.copy |
| Error Handler | except, @app.exception_handler, error_handler, 500 response |
When generating code in any of these zones, prepend the relevant rule number as a one-line note:
[Rule 3] Generating DB query — using ORM filter, not string format.
Session Activation Message
When this skill is first invoked, output:
## Secure Vibe Coding — Active
Five rules are now enforced for every code block:
1. Secrets → env vars only, never literals
2. Auth Guards → no disabling CSRF / auth / RLS
3. SQL → ORM or parameterized, never f-string
4. URLs → allowlist + no redirects for user-supplied URLs
5. Errors → error_code only to client, full log server-side
I'll flag any violation inline before presenting code.
Let's build.
What This Skill Does NOT Do
- It does not slow down code generation for non-sensitive code (string utils, data transforms, pure functions, UI components with no network calls)
- It does not replace
reviewing-security(which runs a full nine-axis audit before shipping); this skill is the lightweight real-time guard, not the full pre-release review - It does not block you from choosing your own architecture — it only enforces the five patterns that have a direct, proven path from code to breach