--- title: "The Betrayal of AI-Written Code" — 5 Technical Vulnerabilities in Vibe-Coded Apps date: 2026-09-23 time: "23:20" model: admin category: knowhow summary: An analysis with real code examples of 5 security vulnerabilities hidden in vibe-coded apps: missing authorization checks, SQL injection, vulnerable libraries, information exposure, and a practical security checklist. tags: vibe-coding,security,vulnerability,SQL-injection,XSS,secure-coding,AI-coding --- # The Betrayal of AI-Written Code — 5 Technical Vulnerabilities in Vibe-Coded Apps "Wow, this was built with a single prompt?" The moment you admired the code AI made for you, you probably thought something like this: "This is actually pretty good?" But there is a good chance that code has a hole punched through it that lets anyone walk off with your users' data. This article lays out **the five most common and most fatal security vulnerabilities** in vibe-coded apps, together with the actual code. ## 1. Missing Authorization Checks (IDOR) **The code AI wrote:** ```javascript // Express.js — order lookup API app.get('/api/orders/:orderId', (req, res) => { const orderId = req.params.orderId; // This is the problem: anyone who requests it can see every order db.query('SELECT * FROM orders WHERE id = ?', [orderId], (err, result) => { if (err) return res.status(500).json({ error: err.message }); res.json(result[0]); }); }); ``` **The risk:** If someone requests `/api/orders/1`, `/api/orders/2`, `/api/orders/3` in sequence, they can **read the order history of every other user**. This is exactly the IDOR (Insecure Direct Object Reference) vulnerability. **Attack scenario:** ``` 1. Look up my order: GET /api/orders/42 → normal 2. Look up someone else's order: GET /api/orders/43 → another user's payment info exposed 3. Loop through it: iterate from 1 to 1000 → the entire user base leaks ``` **The correct code:** ```javascript app.get('/api/orders/:orderId', authenticateToken, (req, res) => { const orderId = req.params.orderId; const userId = req.user.id; // current user ID extracted from the JWT db.query( 'SELECT * FROM orders WHERE id = ? AND user_id = ?', [orderId, userId], (err, result) => { if (err) return res.status(500).json({ error: 'server error' }); if (!result.length) return res.status(404).json({ error: 'order not found' }); res.json(result[0]); } ); }); ``` **The difference:** one condition was added: `AND user_id = ?`. Only the orders of the currently logged-in user are queried. ## 2. SQL Injection **The code AI wrote:** ```python # Flask — search feature @app.route('/search') def search(): keyword = request.args.get('q') # direct string interpolation → vulnerable to injection query = f"SELECT * FROM products WHERE name LIKE '%{keyword}%'" cursor.execute(query) results = cursor.fetchall() return jsonify(results) ``` **Attack scenario:** ``` Normal input: http://app.com/search?q=laptop → SELECT * FROM products WHERE name LIKE '%laptop%' Malicious input: http://app.com/search?q=' OR '1'='1 → SELECT * FROM products WHERE name LIKE '%' OR '1'='1%' → every product record leaks More malicious: http://app.com/search?q='; DROP TABLE products;-- → the table itself is deleted ``` **The correct code:** ```python @app.route('/search') def search(): keyword = request.args.get('q') # use bound parameters → prevents injection cursor.execute( "SELECT * FROM products WHERE name LIKE %s", (f'%{keyword}%',) ) results = cursor.fetchall() return jsonify(results) ``` **Key point:** using `?` or `%s` binding instead of an `f-string` makes the input treated as a "value" rather than SQL syntax. ## 3. XSS (Cross-Site Scripting) **The code AI wrote:** ```html
``` **Attack scenario:** ``` Normal URL: profile.html?user=John →

John's profile

(normal) Malicious URL: profile.html?user= → the user's cookie (session token) is sent to the attacker's server → the attacker hijacks the session and uses the app while logged in ``` **The correct code:** ```html
``` **Key point:** using `textContent` instead of `innerHTML` means the input is not interpreted as HTML. ## 4. Hardcoded Sensitive Information **The code AI wrote:** ```python # Database connection import psycopg2 conn = psycopg2.connect( host="db.mycompany.com", database="production", user="admin", password="SuperSecret123!" # ← here ) # Email sending SMTP_PASSWORD = "GmailAppPassword456" # ← here # Payment API STRIPE_SECRET_KEY = "sk_live_4eC39HqLyjWDarjtT1zdp7dc" # ← here ``` **The risk:** What happens if this code goes up on GitHub? Within five minutes, automated scanning bots find these keys and use them. A Stripe key beginning with `sk_live_` is immediately used for payment fraud. **A real incident:** Automated bots that scan GitHub for `password`, `secret`, `api_key`, and the like run around the clock. The moment you push the code, the sensitive information has already leaked. **The correct code:** ```python # .env file (never committed to GitHub) # DB_PASSWORD=SuperSecret123! # SMTP_PASSWORD=GmailAppPassword456 # STRIPE_SECRET_KEY=sk_live_4eC39HqLyjWDarjtT1zdp7dc import os from dotenv import load_dotenv load_dotenv() conn = psycopg2.connect( host=os.environ.get('DB_HOST'), database=os.environ.get('DB_NAME'), user=os.environ.get('DB_USER'), password=os.environ.get('DB_PASSWORD') ) ``` **Always add to .gitignore:** ``` .env *.key *.pem config/secrets.json ``` ## 5. Information Exposure Through Poor Error Handling **The code AI wrote:** ```javascript // Express.js — global error handler app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ error: err.message, stack: err.stack // ← fatal }); }); ``` **The risk:** When an error occurs on a production server, the following information is exposed in the user's browser: ```json { "error": "Cannot read property 'id' of undefined", "stack": "TypeError: Cannot read property 'id' of undefined\n at /app/src/routes/orders.js:15:23\n at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)\n at /app/node_modules/express/lib/router/index.js:28:3\n at Function.handle (/app/node_modules/express/lib/router/index.js:88:3)" } ``` With this information an attacker can: - **map the server directory structure** (`/app/src/routes/orders.js`) - **identify the framework version** (`express/lib/router`) - **trace code line numbers** (`orders.js:15:23`) - **design follow-up attacks** **The correct code:** ```javascript // Global error handler app.use((err, req, res, next) => { console.error(err.stack); // log on the server only // Production: never expose detailed errors if (process.env.NODE_ENV === 'production') { res.status(500).json({ error: 'An internal server error occurred.' }); } else { // Show detailed errors only in development res.status(500).json({ error: err.message, stack: err.stack }); } }); ``` ## 6. A Practical Security Checklist Before deploying a vibe-coded app to production, always verify: ### Backend - [ ] **Input validation**: is SQL injection filtering applied to every user input? - [ ] **Authentication and authorization**: is the JWT/session token re-verified on every API request? - [ ] **Injection prevention**: are bound parameters used in SQL queries? - [ ] **Error handling**: are detailed error messages not exposed on the production server? - [ ] **Sensitive information isolation**: are API keys and passwords in `.env` and registered in `.gitignore`? ### Frontend - [ ] **XSS prevention**: is `textContent` used instead of `innerHTML`? - [ ] **CSRF protection**: is a CSRF token included in POST/PUT/DELETE requests? - [ ] **Console log removal**: are there no `console.log()` calls left in production code? ### Infrastructure - [ ] **Dependency audit**: are there no vulnerable libraries according to `npm audit` or `pip check`? - [ ] **HTTPS**: is all communication encrypted over HTTPS? - [ ] **Debug mode OFF**: is `DEBUG=True` not enabled in the production environment? ```bash # npm dependency audit npm audit npm audit fix # pip dependency audit pip check pip-audit # SonarQube static analysis (example) sonar-scanner -Dsonar.projectKey=myapp -Dsonar.sources=./src ``` ## 7. Conclusion — The Army Is Safe Only When the Commander Is Smart AI is an excellent coding tool. But AI does not "take responsibility" for security. The security of AI-written code is **entirely on the user**. > **"AI-written code is perfectly insecure, at exactly the level that makes it ripe for abuse by criminals."** If you don't know what SQL injection is, the search feature AI built for you can leak your entire database. If you don't know what XSS is, the profile page AI built for you can get your users' sessions hijacked. If you do vibe coding, you should at least know **what these five vulnerabilities are, why they are dangerous, and how to fix them**. Otherwise, the app you built will betray your users. > **"The army (AI) is safe only when the commander (human) is smart."** --- *This article is based on the operator's personal hands-on experience and perspective.*