The Vibe Coding Velocity Risk

Andrej Karpathy coined vibe coding in February 2025. BrassCoders scanned 15 AI-generated Python files and found real issues in 9 — with zero generation-time warnings. That gap is the velocity risk.

Copper Sun Brass Team · · 7 min read
securityai-code-reviewengineering

Andrej Karpathy coined the term in February 2025, and the definition was disarmingly simple: you describe what you want, the AI writes it, you barely read it. The code ships fast. So do the bugs.

That gap — confident generation, silent on security — is the velocity risk. It’s not a theory. BrassCoders scanned 15 AI-generated Python files and found real security or performance issues in 9 of them, with zero generation-time warnings from the model in any case.

What Vibe Coding Actually Is

BrassCoders traces the practice directly to Karpathy’s February 2025 post: the developer surrenders authorship to the AI, vibe-checks the output, and ships. Not “reviews with AI help.” Not “AI drafts, human edits.” The point of vibe coding is that the human barely reads the code. Speed is the value proposition; verification is what gets compressed.

That description captures a real workflow. Solo developers and small teams operating at prototype speed often choose exactly this tradeoff. The blank page problem disappears. The first 80% of any implementation arrives in minutes. Those are genuine advantages.

What vibe coding doesn’t deliver is a review. The AI generates code the way a confident but context-free collaborator would — applying plausible patterns from training data, assembled quickly, without knowledge of your deployment context, your data volumes, or your secret management conventions. The model produces what statistically fits the prompt. Safe code and plausible-looking code overlap most of the time, but not all of it.

Simon Willison put it directly in a 2024 post on AI-assisted coding concerns: the tool produces plausible-looking code; the developer who does not read it carefully will not catch the security issue; the issue ships. Vibe coding makes this structural rather than accidental.

The Generation-Time Warning Gap

BrassCoders treats the generation-time warning gap as the central problem in vibe-coding security — the space between when the model produces an insecure pattern and when anyone finds out. In a standard development workflow, that gap closes eventually: code review, a security audit, a scanner in CI. Vibe coding compresses every one of those steps.

The model itself does not close the gap. Unless a developer explicitly prompts for a security review — and sometimes even then — the model generates the most statistically common completion for the task. Insecure patterns are common in training data. A Flask endpoint that builds a SQL query from string formatting is not unusual in the corpus the model trained on. The model produces it without hesitation and without warning.

This is not a failure of capability. A frontier model asked to review its own code will catch security issues on request. BrassCoders’s vibe-coding-safety-net benchmark found exactly that: the same model that generated code with a hardcoded credential identified it when asked to review. The gap is not about what the model knows. It is about what the vibe-coding workflow asks it to do.

The result is a structural silence. Code ships. The issue is present. No one was told.

What the N=15 Corpus Found

BrassCoders published a reproducible corpus study — 15 Python files generated by an AI assistant from realistic coding prompts (web handlers, data processing, subprocess calls, auth, config), scanned with brasscoders --offline scan, pre-registered before the first scan ran. The headline data is the finding rate.

The full results and reproduce instructions are in the ai-python-static-analysis-benchmark post.

53 findings across 15 files. Every file had at least one. After triage, 9 of the 15 carried a real security or performance issue. The canonical examples: SQL injection built from string formatting, command injection via shell=True, hardcoded credentials, yaml.load without a safe loader, a requests call with no timeout, Flask debug=True in a handler.

Zero of these generated a warning when the code was written. The model produced them, returned the code, and stopped.

The corpus is a single-model study (15 files is directional, not definitive), and BrassCoders’s findings include false positives by design — the triage layer exists for a reason. But the 9/15 signal is consistent with the controlled research. Perry et al.’s ACM CCS 2023 study, the most rigorous controlled study of this question, found that participants using an AI assistant wrote significantly more insecure code than those without one, across injection, authorization, and cryptographic categories — and rated their code as more secure. The gap between the real rate and the perceived rate is the mechanism that vibe coding relies on and that makes it dangerous.

The full research index for this study cluster, with citations and links to primary sources, is at coppersun.dev/research/vibe-coding-velocity-risk/.

Why More Capable Models Don’t Close the Gap

BrassCoders is built on the premise that model capability and code safety are not the same axis, and the published data agrees. Veracode’s State of Software Security 2026 found that 45% of AI-generated code still introduced at least one OWASP Top 10 vulnerability on first generation — a figure that had not fallen as the models got more fluent.

Fluency and safety are not the same axis. Newer models produce cleaner code, better idiomatic structure, more consistent naming. They don’t produce safer code at the rate you’d expect, because the insecure patterns they reproduce are not errors of syntax. They’re errors of context.

The capability paradox — why better models may make this harder, not easier — is the subject of the why-better-ai-models-make-bugs-harder-to-catch post. The short version: cleaner-looking code earns more reviewer trust, and more reviewer trust means the one insecure line gets less scrutiny. A model that produces fluent, idiomatic code with one SQL injection buried in it is more dangerous than a model that produces obviously ugly code with the same injection. The injection is easier to miss.

Liu et al.’s Lost in the Middle (2023) showed the attention problem directly: language models attend strongly to the start and end of a long input and lose the middle. A bug that spans the middle of a large file, or crosses several files, sits in the model’s blind spot whether it’s generating or reviewing. Better models do not fix this structurally. They have context windows, not call graphs.

BrassCoders runs Pyre/Pysa’s interprocedural taint analysis, which walks the call graph. It has no context window. The taint flow from an API route through a helper to a database call exists in the static graph regardless of file structure.

The 30-Second Gate

BrassCoders is the gate that vibe coding removes. A 30-second pre-commit scan puts it back.

Install the OSS core — pip install brasscoders — and add it to your pre-commit workflow:

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: brasscoders
        name: BrassCoders security scan
        entry: brasscoders --offline scan
        language: system
        pass_filenames: false

The hook exits non-zero on CRITICAL findings and blocks the commit. Hardcoded secrets, SQL injection patterns, command injection, weak cryptography — caught before they hit the repo. The AI-generated code still ships fast. It ships with a scan behind it.

BrassCoders runs 12 scanners — Bandit, Pylint, Pyre/Pysa, Semgrep, ast-grep, detect-secrets, and six custom detectors covering secrets, privacy, AI-patterns, performance, content moderation, and JavaScript/TypeScript — and makes zero outbound network calls in OSS-core mode.

No account needed. Apache 2.0 licensed.

BrassCoders Paid ($12/dev/month) adds AI-powered enrichment — a hosted gateway that deduplicates and ranks findings against a project signature — for teams where triage volume is the bottleneck. The OSS core catches the structural issues either way.

Vibe coding is not going away. The workflow is too fast, the blank-page elimination too real. The question is whether the gate goes back in the pipeline. pip install brasscoders takes 15 seconds. The pre-commit hook config is five lines. That’s the full cost of closing the gap.

Frequently Asked Questions

Is vibe coding safe for production?

Not without a deterministic scanning gate. BrassCoders's N=15 AI-code-findings corpus found real security or performance issues in 9 of 15 AI-generated Python files — with zero generation-time warnings from the model. Vibe coding speeds up authorship; it doesn't add safety. The scan that takes 30 seconds before your commit is what bridges that gap.

Does vibe coding produce more bugs than human-written code?

The empirical research says yes, at a meaningful rate. Perry et al. (ACM CCS 2023) found that participants using an AI assistant wrote significantly more insecure code than those without one — across injection, authorization, and cryptographic categories — and were more likely to believe their code was secure. BrassCoders's own N=15 corpus confirms a high finding rate on un-planted AI-generated Python: 9 of 15 files carried a real issue.

What's the fastest way to add security to a vibe coding workflow?

Run brasscoders scan before the PR. BrassCoders is an offline-capable deterministic scanner — no network calls by default, no account needed for the OSS core. Add it as a pre-commit hook and the 12-scanner sweep runs automatically before every commit. The gate vibe coding removes from your mental workflow is now back in the pipeline.

Does BrassCoders slow down vibe coding?

No. BrassCoders runs offline, scans in seconds, and integrates as a pre-commit hook that fires once per commit rather than once per file edit. A typical codebase scan completes in under 30 seconds. The throughput cost is small; the cost of shipping a hardcoded credential or a SQL injection pattern without it is not.

What does 'generation-time warning gap' mean?

When an AI coding assistant generates code with a security issue, it rarely proactively tells you. It produces the code confidently. The generation-time warning gap is the space between 'model generates insecure pattern' and 'developer is told there is a problem' — a gap that closes only when the developer explicitly asks for a security review, or when a deterministic scanner like BrassCoders runs on the output.