use caseofficial ogbuilds guide

The 6 most common security findings in vibe-coded apps, measured rather than guessed

By ogbuilds, the studio behind quality·vibes · updated 2026-06-11

the short answer

When we ran the quality·vibes rules engine over 549 public self-described AI/vibe-coded GitHub repos (July 2026), the six most common security findings were dangerouslySetInnerHTML usage (42.6% of repos), a .gitignore that doesn't cover .env files (35.7%), no .gitignore at all (15.3%), curl-piped-to-shell installs (9.8%), hardcoded passwords (9.3%), and wildcard CORS (11.3%). Each one has a mechanical fix, listed on this page.

Most lists of "common security mistakes" are assembled from vibes. This one is counted: we ran the quality·vibes rules engine over 549 public GitHub repos that describe themselves as AI- or vibe-coded (data collected July 2026) and ranked the findings by how many repos each appeared in. The AI pass was off, so these are deterministic, reproducible hits.

#1-#3: dangerouslySetInnerHTML and the .gitignore pair

dangerouslySetInnerHTML topped the list at 42.6% of repos. React names it dangerously for a reason: it injects raw HTML, and if any of that HTML ever derives from user input, it's cross-site scripting. Generated code reaches for it because it's the shortest path to rendering rich content. The fix: render text as text, and when you do need HTML, sanitise it with a maintained library like DOMPurify before it goes in. Never interpolate user input into it raw.

Numbers two and three are the same discipline failing twice: 35.7% of repos have a .gitignore that doesn't cover .env files, and 15.3% have no .gitignore at all. Both are prevention failures. The repo may be clean today, but nothing stops tomorrow's .env commit. The fix takes minutes: add a root .gitignore covering .env, key files, and your stack's build artifacts. It's the single cheapest security improvement in this study, which makes its absence in 15% of repos the quietest bad news in it.

#4-#5: curl | sh installs and hardcoded passwords

curl-piped-to-shell appeared in 9.8% of repos: an install step that downloads a script from a URL and executes it immediately, usually in a README or setup script. You're running unreviewed remote code with your local privileges, and the script can change after you've vetted it. The fix: download first, read it, pin to a specific version or checksum, then run. Or take the package-manager install the project almost always also offers.

Hardcoded passwords also hit 9.3% of repos: a password literal sitting in committed code. This is the finding that overlaps with the study's scariest aggregate, the 20.4% of repos with at least one secrets finding of some kind. The fix is the standard two-step. Move the value to an environment variable, and if the repo is public, rotate the credential first, because git history keeps what you committed and deletion alone doesn't end the exposure.

#6: wildcard CORS, mostly harmless, and why we're saying so

Wildcard CORS (Access-Control-Allow-Origin: *) showed up in 11.3% of repos. We originally listed it as a security finding. A reader challenged that, and they were right, so here's the correction.

On its own a wildcard gives an attacker nothing. Browsers refuse to attach cookies to a request whose response allows any origin, so a malicious page reading your API learns exactly what a logged-out visitor could have fetched anyway. If the data is public, this is a non-issue.

It turns dangerous in one specific pairing: a wildcard plus credentials. We tested four libraries. FastAPI/Starlette, flask-cors and django-cors-headers all quietly rewrite that '*' into whatever origin asked, and send Access-Control-Allow-Credentials: true alongside it, which the browser will hand over. Express's cors package doesn't; it sends a literal '*' and the read gets blocked. So the same config is a real hole in Python and a shrug in Node.

We went back through all 120 wildcard hits to see which were which. 40 weren't running code at all: markdown, prompt-library templates, another scanner's rule definitions, good/bad teaching snippets. 76 were bare wildcards with no credentials. Two repos were exploitable. That's 0.4%, against the 11.3% we'd published. One repo we'd flagged had shipped a guard that refuses to boot on the invalid combination, and we'd cited its own warning message back at it.

So the scanner now reports the wildcard only where it's paired with credentials. A bare one produces nothing at all. We dropped that check rather than hand you 42 findings that all resolve to "this is probably fine". Treat the 11.3% as a measure of what AI codegen emits by default rather than a count of vulnerable apps.

All six findings survive the does-it-run feedback loop, because none of them stops an app working. That's also what makes a rules-based scan the right instrument: the patterns are fixed, so they count cleanly. About this study: 549 public repos self-described as AI- or vibe-coded, scanned by the quality·vibes rules engine, data collected July 2026. Per-rule reporting caps mean the per-repo counts behind these percentages are floors.

The top 6 security findings across 549 vibe-coded repos (quality·vibes rules engine, July 2026)

Finding% of reposThe fix
dangerouslySetInnerHTML42.6%Render text as text; sanitise unavoidable HTML with DOMPurify
.gitignore missing .env coverage35.7%Add .env, key files, and artifacts to the root .gitignore
No .gitignore at all15.3%Add one. Minutes of work, and it prevents most future data-exposure findings
curl | sh install9.8%Download, read, pin a version or checksum, or use the package manager
Hardcoded password9.3%Move to an env var; rotate first if the repo is public
Wildcard CORS11.3% (0.4% exploitable)Only a hole when paired with credentials. Then allowlist your real origins

frequently asked

Is dangerouslySetInnerHTML always a vulnerability?

No. With static, trusted HTML it's a smell rather than a hole. It becomes XSS the moment user-influenced data flows into it, and in a generated codebase nobody has audited that flow. The scan flags it so you check; the fix (sanitise or render as text) is cheap either way.

Why do two of the top three involve .gitignore?

Because nobody prompts for one. The AI was asked for an app, not repo hygiene, so a quarter of self-described vibe-coded repos ship with no .gitignore or one that won't stop a .env commit. No other five-minute fix in the study prevents as much damage.

Where do these percentages come from?

From our corpus study: the quality·vibes rules engine run over 549 public GitHub repos that describe themselves as AI- or vibe-coded, collected July 2026, AI pass off. Each percentage is the share of repos with at least one instance of that finding. Full method is on the methodology page.

How do I check my repo for all six at once?

Paste the public repo link into quality·vibes. The same rules that produced these numbers run against your code, along with the Claude review the study switched off, and every finding comes back with file, line, and a paste-ready fix prompt.

Last updated June 11, 2026

ready to try quality·vibes?

scan your repo