How do I scan my code for security vulnerabilities?

Direct answer

Two different scans, and you need both. Dependency scanning checks the libraries you installed against known CVEs and is free on GitHub via Dependabot. Static analysis checks the code you wrote, and has free options too. Start with dependencies because it takes minutes, then add code scanning to your pipeline so it runs on every change rather than on request.

Muhammad HasanUpdated

"Scanning code" covers two separate things that catch entirely different problems, and teams often set up one and assume they're covered.

Dependencies first, because it's free

Software composition analysis checks the libraries you pulled in against databases of known vulnerabilities. If you're on GitHub, Dependabot does this without you doing anything beyond enabling it in repository settings, and it will open pull requests to bump versions.

Do this first. It takes minutes, it costs nothing, and a large share of real-world breaches trace back to a dependency with a published CVE that nobody updated.

What it doesn't do is look at code you wrote. If your own authorisation logic is broken, Dependabot has no opinion about it.

Then your own code

Static analysis reads your source and looks for flaws in it, injection, hardcoded secrets, unsafe deserialisation, missing authorisation checks.

Free options exist. GitHub's CodeQL is available on public repositories and through Code Security on private ones. Semgrep has a free tier with a large community rule registry. Both will find real bugs, and either is better than nothing by a wide margin.

Set it to run in CI on every pull request rather than manually. A scan you have to remember to run is a scan that stops happening in about three weeks.

What to expect the first time

Point any scanner at an existing codebase and you'll get a lot of results. Hundreds is normal, thousands isn't unusual, and most teams' first reaction is to close the tab.

The approach that works is to baseline. Accept everything currently in the codebase as known debt, configure the scanner to fail builds only on newly introduced findings, then work through the backlog by severity separately. That way the tool stops being a blocker on day one and starts preventing the problem getting worse immediately.

Where scanners are weak

Worth knowing before you rely on one.

Rule-based scanners work by matching code against patterns for known-bad constructs. That's effective for things with a recognisable shape. A hardcoded key, a string-concatenated SQL query, and much weaker for flaws that are an absence rather than a construct. A database query that should filter by the current user and doesn't looks exactly like a correct query.

This is measurable and we measured it. RealVuln runs 26 scanners over 66 Python repositories with 1,903 hand-labelled vulnerabilities, and the per-class breakdown is the useful part. On SQL injection, LLM-based scanners recalled 96% against 37% for rule-based ones. On insecure deserialisation, 100% against 57%. On hardcoded secrets, where the bug has a distinctive shape, the gap narrows a lot.

So it isn't that rule-based scanning doesn't work. It works on the classes that reduce to a pattern and falls away on the ones that don't. Labels, scanner outputs and scoring code are all published, and Kolega is one of the scanners in the run, which is why they are.

So the practical position is: free tools are worth setting up today, and you should be clear-eyed that they're catching a minority of what's there. Tools using dataflow analysis rather than pattern matching do better on the semantic cases, which is the approach Kolega takes, and the same benchmark shows the gap.

Order of operations

  1. Enable Dependabot. Ten minutes.

  2. Add a free static analysis step to CI, on pull requests.

  3. Baseline existing findings so builds don't fail on day one.

  4. Fix new findings as they appear; work the backlog by severity separately.

  5. Reassess tooling once you know what your actual finding rate looks like.

Go deeper

SAST for startups

Related answers

See what your own repository returns

Connect a repo and run a scan. No credit card, no pipeline changes.

Get started for free