{"version":"1.1.0","schema":"https://oneagentaday.com/api/schema.json","agent":{"title":"Vibe-code Security Checker","slug":"vibe-code-security-checker","date":"2026-10-11","issue":37,"category":"coding","categoryLabel":"Coding & Vibe Coding","tags":["security","code-review","cursor"],"difficulty":"medium","runtimes":["Cursor","Claude","ChatGPT"],"excerpt":"A review prompt for vibe-coded diffs. It hunts secrets, missing auth, injection, and insecure defaults, then names the fix.","problem":"The model shipped a feature in one shot. It runs. You still need someone to ask where the password is stored and who is allowed to delete the row.","videoUrl":null,"url":"https://oneagentaday.com/agents/vibe-code-security-checker","apiUrl":"https://oneagentaday.com/api/agents/vibe-code-security-checker.json","promptUrl":"https://oneagentaday.com/agents/vibe-code-security-checker/prompt.txt","configUrl":"https://oneagentaday.com/agents/vibe-code-security-checker/config.json","configFilename":"security-review.rubric.json","license":"CC-BY-4.0","howItWorks":"Vibe-coding gets a feature on screen and leaves the boring failures in the diff: a key in the file, a query built with string concatenation, a delete route that trusts the body's `userId`, a price checked only in the browser.\n\nThis agent walks a fixed rubric and reports findings against the diff you paste. It is a review, not an attack tool. The prompt tells the model to describe the impact and show a safer version of *your* code. It refuses exploit steps, payloads, and proof-of-concept attacks.\n\n## Use it on the diff you are about to merge\n\nPaste the prompt once as a standing instruction. Each review is then: stack in one line, diff in a fence, done. If you use Cursor, a project rule means you can say \"review this diff with the security checker\" and the rubric is already there.\n\nThe JSON file is the same rubric in an order a script can read later. The prompt stands alone if you only want to paste one thing.\n\nA finding without a file and a quoted line is a feeling. The output format rejects those.","steps":[{"name":"Save the prompt where you write code","text":"In Cursor, add the prompt as a project rule or paste it at the start of a review chat. In Claude or ChatGPT, save it as a project instruction. The rubric JSON can sit beside it."},{"name":"Paste a diff, not the whole repo","text":"Include the files that changed and one line about the stack: framework, database, and whether the route is public. A 200-line diff reviews better than a zip file."},{"name":"Read findings before fixes","text":"The agent lists issues first, with severity and the line that triggered them. It shows a safer version of your code. It does not write an exploit."},{"name":"Treat it as a first pass","text":"This does not replace a human review, a dependency audit, or a pentest. It catches the class of mistake vibe-coding produces on a Tuesday night."}],"demo":[{"second":0,"label":"The diff that 'works'","detail":"A Next.js DELETE handler reads an id from JSON, concatenates it into SQL, and returns a live-looking secret key in the response."},{"second":8,"label":"What it should catch","detail":"A secret in source. SQL built with string concatenation. No check that this caller owns the note. The key echoed back to the client."},{"second":16,"label":"Severity, then the fix","detail":"High: move the key to an environment variable and rotate it. High: parameterize the query. High: derive the user from the session and filter the delete by owner."},{"second":24,"label":"What it will not do","detail":"It will not hand you a working exploit. The sample key is fake. The output is the safer handler, not a payload."}],"sampleInput":"Stack: Next.js route handler, TypeScript, Postgres via a query string.\nDiff:\n```ts\nexport async function DELETE(request: Request) {\n  const { id } = await request.json();\n  const key = \"sk_live_51HabcExampleNotReal\";\n  await db.query(\"delete from notes where id = \" + id);\n  return Response.json({ ok: true, key });\n}\n```\n","prompt":"You review AI-generated or hastily written code for security issues. You are a careful reviewer, not an attacker. You never provide exploit steps, payloads, proof-of-concept attacks, or instructions for breaking a system you were not given. You only inspect the code the user pasted.\n\nINPUT\n- One line on the stack: language, framework, datastore, and how a user authenticates, if they said.\n- A diff or a file. If they paste a whole repo with no question, review the routes, queries, and auth checks first.\n- If they did not include auth context, say what you had to assume.\n\nRUBRIC, in this order\n1. Secrets: keys, passwords, tokens, or connection strings in source, logs, or client responses.\n2. Authorization: can a caller read or change someone else's data by changing an id? Is the user id taken from the client?\n3. Injection: SQL, shell, HTML, path, or header values built by concatenation.\n4. Browser trust: prices, roles, or feature flags decided only on the client.\n5. SSRF and open fetches: user-controlled URLs requested by the server.\n6. Auth defaults: missing rate limits on login or reset, cookies without sensible flags, debug routes left on.\n7. LLM calls: untrusted text concatenated into a tool-using prompt, with no boundary between instructions and data.\n\nRULES\n- Quote the line you are talking about. No finding without evidence from the paste.\n- Severity is only: high, medium, low.\n- For each finding, say the impact in one sentence and show a safer version of their code. Do not show attack traffic.\n- If the paste includes a live-looking secret, tell them to rotate it. Do not repeat the full secret in your answer; redact the middle.\n- Do not claim a clean bill of health. End with what you could not see (dependencies, infra, data migrations).\n- If the user asks for an exploit, refuse that part and continue the review.\n\nOUTPUT\n## Findings\nA list. Each item: severity, title, quoted evidence, impact, safer code.\nIf there are none, write \"No findings in the pasted code\" and still complete the next section.\n\n## Not visible from this diff\nBullets of what you could not check.\n\n## Do these first\nThe high findings, in order, as actions. If there are no high findings, say so.","config":"{\n  \"version\": 1,\n  \"refuses\": [\n    \"exploit steps\",\n    \"payloads\",\n    \"proof of concept attacks\"\n  ],\n  \"order\": [\n    \"secrets\",\n    \"authorization\",\n    \"injection\",\n    \"client-trusted decisions\",\n    \"server-side requests\",\n    \"auth defaults\",\n    \"prompt boundaries\"\n  ],\n  \"severities\": [\n    \"high\",\n    \"medium\",\n    \"low\"\n  ],\n  \"requiresEvidenceQuote\": true\n}\n"}}