"Scan my GitHub repo for vulnerabilities" sounds like one job. It is actually four different jobs, and knowing what they are is the difference between a real check and a false sense of completion. This guide walks through all four honestly: what each one covers, what it takes to do by hand, and where the one-click version fits. Everything here can be done for free, and none of it requires a security background.
The four jobs: finding secrets in your code and its history, finding flaws in the code itself, checking your dependencies against known vulnerabilities, and catching exposed configuration. Miss one and the scan has a blind spot exactly where you stopped looking. That blind spot is the usual failure mode of a quick check: someone searches their current files for the word "key", finds nothing, and concludes the repo is clean, while an old commit still carries the database password they removed in week two.
You need nothing special to follow along: your repo, a terminal if you want to do the hand checks, and about a day if you do all four manually. If your app was built with an AI coding tool, the odds that these checks find something are meaningful rather than theoretical, which is a reason to run them, not a reason to feel bad. Everyone's first scan finds something.
Check 1: Secrets and API keys, across your full git history
What it covers: API keys, database passwords, and tokens sitting anywhere in your repository, including in old commits. This is the check with the shortest deadline attached, because automated scrapers watch public repositories continuously, and the scale of key leakage is enormous: in February 2026, researchers at Wiz found a single exposed database revealing roughly 1.5 million API keys.
By hand: the detail that matters is history. Searching your current files misses every key that was committed and later deleted, and git keeps all of it. Checking properly means searching every revision of every file, with commands like git log -p piped through pattern searches for each provider's key format. For a repo of any age, expect an afternoon, and expect to second-guess your patterns. When you find something, rotate the key at its provider first; removal without rotation is cosmetic.
What counts as a secret, since the word hides some surprises:
- API keys for any paid service: payment, email, AI, maps, storage.
- Database connection strings, which often bundle the password into the URL.
- Auth signing secrets (the value your app uses to sign login tokens).
- Webhook signing secrets and OAuth client secrets.
- Anything named
password,token, orsecretin a config file, even a "temporary" one.
Check whether this repository has ever committed a .env file or any other file containing secrets, including in past git history.
If yes:
1. List every secret that was ever committed, with the file and the kind of secret, so I can rotate each one at its provider. Rotation comes first: git history preserves deleted files, so removal alone does not make a leaked key safe.
2. Remove the files from the current code, load the values from environment variables instead, and add the file patterns to .gitignore.
3. Create a .env.example with placeholder values so the setup stays documented.
Also check for config that should not ship: debug mode enabled for production, CORS set to allow any origin, and any test or example endpoints.Check 2: Flaws in the code itself
What it covers: places where your code trusts input it should not, so a crafted request reads your whole database (SQL injection), and routes that hand out private data without checking who is asking (broken access control). If AI wrote much of your code, this check earns its place: Veracode's GenAI code security research found security flaws in roughly 45 percent of AI-generated code samples.
By hand: this is the deep one. You trace every path user input takes into a query, a rendered page, or a command, and you visit every endpoint asking "what happens if someone else calls this?". It is genuine code review, it needs some feel for what wrong looks like, and on a full app it is days, not hours. If you want to sample it rather than do it exhaustively, these five questions catch a large share of what matters:
- Does every database query use parameters, or does any build query text from user input?
- Is user-written content escaped before it is shown to other users?
- Does every private route check the logged-in user on the server, not just in the browser?
- If you change an ID in a URL, can you reach a record that belongs to someone else?
- Do file uploads restrict type and size, and land somewhere that never executes them?
The vibe coding security checklist breaks the highest-value parts of this into questions you can answer one at a time, with prompts that hand the fixing to your AI tool.
Check 3: Dependencies with known vulnerabilities
What it covers: the packages your app is built on. Most of your repo's code is not yours, and some of it has publicly documented vulnerabilities (known CVEs) with fixes already published. Nothing needs discovering here; it only needs comparing.
By hand: the most automatable check. Package managers have built-in audit commands, and GitHub can flag vulnerable dependencies if it's enabled for your repo. The work is in reading the results: separating "urgent, this parses user input" from "technically flagged, practically unreachable", and updating without breaking things. Budget an hour, more on the first pass.
Check 4: Exposed configuration
What it covers: a committed .env file, debug mode switched on in production, CORS rules that allow any origin, test endpoints that shipped. Each is small; each is a door left ajar.
By hand: a focused pass over config files, deploy settings, and framework flags. Quick if you know each framework's sharp edges, slower if you are learning them as you go. The fix prompt in Check 1 covers the config sweep too. A useful trick for this one: trigger an error in your deployed app on purpose, with a junk form submission or a malformed URL. If the response includes a stack trace, file paths, or query text, debug output is on in production, and whatever else the config pass finds, that one is worth fixing today.
A note on public vs private repos
Every check here applies to both, with one difference in urgency. A secret in a public repo is effectively already found: scrapers index public GitHub continuously, so Check 1 on a public repo is an emergency drill, rotate first and ask questions later. A private repo buys you time, not immunity; the secret still leaks the day the repo goes public, gets forked into a public copy, or gets cloned to a laptop that walks away. And Checks 2 through 4 do not care about repo visibility at all, because attackers meet your deployed app, not your source. An open endpoint is equally open whether the code behind it is public or private.
How often to re-run all this
A scan describes your repo on the day you ran it. Three things quietly invalidate it: new code (every AI-generated feature is unreviewed code until something reads it), new disclosures (a dependency that was fine last month may have a published vulnerability today), and new configuration (a debug flag flipped during last week's late-night fix). A reasonable rhythm for a solo builder: a full pass now, then a re-scan after any feature that touches auth, payments, or user data, and a monthly dependency check even in quiet months. By hand, that rhythm is a real commitment. Automated, it is a calendar reminder.
The one-click alternative, honestly framed
Everything above can be done by hand for free, and now you know what "done" means: history searched, input paths traced, dependencies compared, config swept. The realistic total is a day or more of careful work, repeated every time the code changes meaningfully.
The alternative is to let a scanner run all four categories in one pass. VibeCheck Hub connects to your GitHub repo with read-only access and runs industry-grade open-source engines across all four: secret and API-key detection across your full git history, injection and access-control analysis of your code, dependency checks against known-vulnerability databases, and exposed-config detection. A scan takes about two minutes, findings arrive in plain English, worst first, and each comes with a fix prompt to paste into the AI tool you already use. The free plan covers 8 scans a month on one repo, no card required.
What a scan, ours included, cannot do: it reads your code, so it cannot catch business-logic flaws (your discount code being reusable forever is working code), it cannot know whether a leaked key was already copied before you rotated it, and it cannot stop social engineering. A scanner's job is to make the checkable things actually checked, so your attention is free for the judgment calls.
If your app was built with an AI tool, keep going with the complete vibe coding security checklist, and if it is a Lovable app, the Lovable security checklist covers the Supabase-specific checks a repo scan alone will not see.