#1–#3: dangerouslySetInnerHTML and the .gitignore pair
dangerouslySetInnerHTML topped the list at 33.3% 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 genuinely need HTML, sanitise it with a maintained library like DOMPurify first — never interpolate user input into it raw.
Numbers two and three are the same discipline failing twice: 26.3% of repos have a .gitignore that doesn't cover .env files, and 23.2% have no .gitignore at all. Both are prevention failures — the repo may be clean today, but nothing stops tomorrow's .env commit. The fix is 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 a quarter of repos the study's quietest bad news.
#4–#5: curl | sh installs and hardcoded passwords
curl-piped-to-shell appeared in 12.1% 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 prefer the package-manager install the project almost always also offers.
Hardcoded passwords also hit 12.1% of repos — a password literal sitting in committed code. This is the finding that overlaps with the study's scariest aggregate (21.2% of repos had 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 — git history keeps what you committed, so deletion alone doesn't end the exposure.
#6: wildcard CORS — and how to read the list as a whole
Wildcard CORS (Access-Control-Allow-Origin: *) showed up in 10.1% of repos. It tells browsers that any website may call your API, which is occasionally a deliberate choice for genuinely public data and otherwise an accident with consequences — especially paired with credentials. The fix: list the origins you actually serve, and keep wildcards away from anything authenticated.
Read together, the six are one story: AI tools generate the most direct working version, and the most direct version skips the guard rails. None of these findings breaks an app, which is why they survive the does-it-run feedback loop and ship. All six are pattern-detectable, which is the point of a rules-based scan — and all six come from this study: 99 public repos self-described as AI- or vibe-coded, scanned by the secure·vibes rules engine, data collected june 10, 2026. Per-rule reporting caps mean the per-repo counts behind these percentages are floors.
The top 6 security findings across 99 vibe-coded repos (secure·vibes rules engine, june 2026)
| Finding | % of repos | The fix |
|---|---|---|
| dangerouslySetInnerHTML | 33.3% | Render text as text; sanitise unavoidable HTML with DOMPurify |
| .gitignore missing .env coverage | 26.3% | Add .env, key files, and artifacts to the root .gitignore |
| No .gitignore at all | 23.2% | Add one — minutes of work, prevents most future data-exposure findings |
| curl | sh install | 12.1% | Download, read, pin a version/checksum — or use the package manager |
| Hardcoded password | 12.1% | Move to an env var; rotate first if the repo is public |
| Wildcard CORS | 10.1% | Allowlist your real origins; never * on authenticated endpoints |
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. It's the highest-leverage five-minute fix in the study.
- Where do these percentages come from?
- From our corpus study: the secure·vibes rules engine run over 99 public GitHub repos that describe themselves as AI- or vibe-coded, collected june 10, 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 secure·vibes. The same rules that produced these numbers run against your code — plus a Claude review the study deliberately switched off — and every finding comes back with file, line, and a paste-ready fix prompt.
Last updated June 11, 2026