How to Build Secure Apps with AI-Generated Code: A Practical Security Guide
Problem
When I use AI coding assistants like Claude Code or ChatGPT to generate code, I get working solutions fast. But I kept wondering: is this code actually secure enough for production?
I tried deploying an AI-generated Flask app last month and nearly shipped a glaring SQL injection vulnerability. The code worked perfectly in my tests, but a security scan revealed the flaw before it reached production.
That close call made me realize something important: AI generates code that works, but it doesn’t guarantee code that’s secure.
What Happened?
I was building a simple user lookup feature and asked Claude to write the database query. Here’s what I got:
# AI-generated code - INSECUREdef get_user(user_id): query = f"SELECT * FROM users WHERE id = {user_id}" return db.execute(query)The code ran fine in my tests. I passed integers, got back users. Everything worked. But when I ran a security scan, it flagged a critical SQL injection vulnerability.
If I had deployed this, an attacker could have passed 1 OR 1=1 as the user_id and dumped my entire user table.
The Real Problem with AI-Generated Code
I dug into this and found that security risks in AI-generated code aren’t random accidents. They follow predictable patterns:
Inconsistent Security Prompts
I tried asking different AI assistants to “write secure code” for the same feature. I got different security implementations each time. Sometimes parameterized queries, sometimes not. Sometimes input validation, sometimes forgotten.
The r/vibecoding community put it bluntly: “LLM security prompts are inconsistent.” You can’t rely on prompt engineering alone for security.
Training Data Vulnerabilities
AI models learn from public code repositories. They’ve seen millions of code examples, including insecure ones. When they generate code, they might reproduce patterns that were common in training data but are now considered vulnerable.
Context Blindness
My AI assistant doesn’t know about my application’s security context. It doesn’t know if this endpoint is public-facing or internal, if the data is sensitive or not, what authentication system I’m using.
Dependency Risks
When AI suggests packages, it doesn’t check for known CVEs. I’ve had AI suggest packages that were deprecated years ago for security reasons.
Common Vulnerabilities I’ve Found
Here are the patterns I now actively scan for:
Leaked Secrets
# AI often generates this - NEVER commit thisAPI_KEY = "sk-proj-xxxxx"DATABASE_PASSWORD = "my_secret_password"SQL Injection
# AI may generate thisdef search_users(name): query = f"SELECT * FROM users WHERE name LIKE '%{name}%'" return db.execute(query)Command Injection
# AI may generate thisdef convert_file(filename): os.system(f"convert {filename} output.png")Path Traversal
# AI may generate thisdef read_config(path): with open(f"/app/configs/{path}") as f: return f.read()Missing CSRF Protection
# AI may generate this - missing CSRF token@app.route("/delete/<id>", methods=["POST"])def delete_item(id): db.delete(id) return "Deleted"The Solution: A Multi-Layer Security Workflow
After my near-miss, I implemented a security-first workflow for all AI-generated code.
Layer 1: Local Security Scanning
I installed Stageclear.dev, a CLI tool specifically built for vibe coders:
# Install Stageclearcurl -sSL https://stageclear.dev/install | bash
# Scan my AI-generated codestageclear scan ./my-projectThe output immediately flagged my issues:
[CRITICAL] Leaked secret: API_KEY found in config.py:12[HIGH] SQL injection vulnerability in queries.py:45[MEDIUM] DEBUG=True in production settings.py[INFO] Consider adding CSRF middlewareWhat I like about Stageclear is that it runs locally and uses “authentic security scanners” rather than relying on AI reasoning. It catches issues before they ever leave my machine.
Layer 2: Fix the Vulnerabilities
After the scan, I fixed each issue:
# SECURE - Use environment variablesimport os
API_KEY = os.environ.get("API_KEY")if not API_KEY: raise ValueError("API_KEY environment variable not set")# SECURE - Parameterized queriesdef get_user(user_id): query = "SELECT * FROM users WHERE id = ?" return db.execute(query, (user_id,))
def search_users(name): query = "SELECT * FROM users WHERE name LIKE ?" return db.execute(query, (f"%{name}%",))# SECURE - Use subprocess with list argumentsimport subprocess
def convert_file(filename): # Validate filename first if not filename.isalnum(): raise ValueError("Invalid filename") subprocess.run(["convert", filename, "output.png"], check=True)Layer 3: Configuration Security
AI often generates insecure defaults for configuration:
# AI may generate this (INSECURE)DEBUG = TrueALLOWED_HOSTS = ["*"]SECRET_KEY = "dev-secret-key"CORS_ALLOW_ALL_ORIGINS = TrueI changed these to:
# SECURE configurationimport os
DEBUG = os.environ.get("DEBUG", "False").lower() == "true"ALLOWED_HOSTS = os.environ.get("ALLOWED_HOSTS", "localhost").split(",")SECRET_KEY = os.environ.get("SECRET_KEY")if not SECRET_KEY: raise ValueError("SECRET_KEY environment variable not set")CORS_ALLOWED_ORIGINS = os.environ.get("CORS_ORIGINS", "").split(",")Layer 4: Static Analysis Tools
I added these to my CI/CD pipeline:
name: Security Scan
on: [push, pull_request]
jobs: security: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Run Bandit (Python security linter) run: pip install bandit && bandit -r ./src
- name: Run Safety (check dependencies for CVEs) run: pip install safety && safety check
- name: Run Semgrep uses: returntocorp/semgrep-action@v1Layer 5: Human Review Checklist
I never deploy AI code without reviewing these:
- Authentication and authorization logic
- Input validation on all user-provided data
- No hardcoded credentials or secrets
- Proper error handling (no stack traces to users)
- Rate limiting on public endpoints
- Security headers configured
Why Traditional Security Prompts Fail
I tried prompting for secure code:
Write secure Python code for user authentication with proper input validation, parameterized queries, and no hardcoded secrets.The result? Better than unprompted code, but still had issues:
- Missing rate limiting
- Incomplete input validation
- Weak password requirements
- No CSRF tokens
The OWASP GenAI Security Project warns: “Neglecting to validate LLM outputs may lead to downstream security exploits, including code execution that compromises systems and exposes data.”
The problem is that prompt engineering is not a security control. AI assistants respond inconsistently, miss context, and can’t guarantee comprehensive security coverage.
Other Tools Worth Knowing
From the r/vibecoding community, I found these helpful:
Vibecheck.expert: Gives a “Vibe Score” (0-100) for code quality and security. Useful for quick production readiness checks.
Vibe.rehab: Analyzes broken AI-generated code and provides security audits. Good for learning what went wrong.
Traditional tools still matter:
- ESLint security plugins for JavaScript
- Bandit for Python
- Semgrep for multiple languages
- Snyk for dependency scanning
The Cost of Skipping Security
I calculated what my near-miss would have cost:
| Scenario | Cost |
|---|---|
| Security scan before deploy | 5 minutes |
| Fix vulnerability during development | 30 minutes |
| Fix vulnerability in production | 4+ hours + incident response |
| Data breach from SQL injection | Reputation damage + potential legal fees |
The OWASP community wisdom holds: fixing vulnerabilities pre-deployment is 10x cheaper than post-deployment.
Summary
In this post, I showed how I secured my AI-generated code before deploying to production. The key point is that AI assistants generate working code, but security must be verified through dedicated scanning tools and human review.
My workflow now:
- Generate code with AI
- Run Stageclear.dev locally before any commit
- Fix flagged issues immediately
- Run static analysis in CI/CD
- Human review for security-critical areas
- Deploy with environment variables and proper configuration
The future of development is AI-assisted, but security remains human-verified. Start with a security-first mindset, use the right tools, and ship with confidence.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 Stageclear.dev - Local Security Scanning for Vibe Coders
- 👨💻 OWASP Top 10 for LLM Applications
- 👨💻 OWASP GenAI Security Project
- 👨💻 Vibecheck.expert - AI Code Quality Analysis
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments