PATH.
Pinned versions do not make findings identical on every machine. semgrep fetches its registry rule packs at run time, and OpenQodex does not pin their version.
Every scanner reads the whole changed file. OpenQodex keeps only the findings on changed lines.
Where scanners come from
Scanners download on first use into~/.openqodex/tools/<scanner>/<version>/. OPENQODEX_HOME moves that folder.
- GitHub release files are checked against the sha256 pinned in the package before they are unpacked.
- semgrep and bandit install from PyPI through uv, into one Python 3.11 that OpenQodex manages. uv comes from your
PATHwhen present. Otherwise OpenQodex downloads a pinned uv. - oxlint installs from npm, with the npm that ships beside your Node. Package install scripts are switched off.
- brakeman and rubocop install from RubyGems with your Ruby’s
gemcommand.
openqodex doctor --install installs every scanner and waits.
Installed scanners take more disk than their downloads. The eight scanners the demo needs take about 700 MB of disk on an Apple Silicon Mac. semgrep with its Python takes about 440 MB of that.
OpenQodex does not install Ruby or Go. Without them, the report lists the scanners that need them as not installed, with the reason.
Status in the report
The report lists every selected scanner with one status. A scanner left out with--only or --skip is not listed.
ran: it ran.no_matching_files: the change holds no file it reads.installing: it is downloading for the first time. It joins the next run.not_installed: it could not be installed here. The reason says why.failed: it ran and broke. The reason holds its error.disabled:scanners.disablenames it, or--offlineskipped it.untrusted: a custom scanner you have not approved.
semgrep
- Version: 1.94.0.
- Runs when: any file changed.
- Needs: Python 3.11, which OpenQodex downloads through uv. About 86 MB with uv and bandit, measured on Apple Silicon.
- Rules: the registry packs
p/default,p/security-auditandp/secrets. - Sends: semgrep fetches those rule packs from the Semgrep registry on each run. It runs with its metrics switched off. The rules are never bundled in the OpenQodex package.
--offlineskips it. The report lists it as disabled.
gitleaks
- Version: 8.21.2.
- Runs when: any file changed.
- Needs: nothing. 2.9 MB on Apple Silicon, 3.0 MB on Linux x64.
- Writes: links the changed files into a temporary folder outside the repo and scans that folder. It reads the repo’s
.gitleaks.tomlorgitleaks.tomlwhen present. - gitleaks writes its raw report to a temporary file outside the repo. That file holds the matched secrets. OpenQodex deletes it when the run ends.
- Sends: nothing.
- Secrets it finds are redacted from the brief, every report file and the terminal. No file OpenQodex keeps holds the secret.
bandit
- Version: 1.9.4.
- Runs when: a
.pyor.pyifile changed. - Needs: the same Python as semgrep.
- Sends: nothing.
ruff
- Version: 0.8.4.
- Runs when: a
.pyor.pyifile changed. - Needs: nothing. 9.9 MB on Apple Silicon, 11.2 MB on Linux x64.
- Reads the repo’s own ruff settings. It runs with fixes and its cache switched off, so it changes no file.
- Sends: nothing.
oxlint
- Version: 1.71.0.
- Runs when: a
.js,.jsx,.ts,.tsx,.mjs,.cjs,.mtsor.ctsfile changed. - Needs: npm, which ships with Node. About 7.3 MB on Apple Silicon, 8.2 MB on Linux x64.
- Uses OpenQodex’s own settings. A config file in the repo is not loaded.
- Sends: nothing.
osv-scanner
- Version: 1.9.2.
- Runs when: one of these lockfiles changed:
package-lock.json,pnpm-lock.yaml,yarn.lock,Cargo.lock,go.mod,go.sum,requirements.txt,Pipfile.lock,poetry.lock,Gemfile.lock,composer.lock,pom.xml,gradle.lockfile,pubspec.lock,mix.lock,conan.lock. - Needs: network access to osv.dev. 31.8 MB on Apple Silicon, 32.1 MB on Linux x64.
- Sends: the names and versions of the dependencies in those lockfiles, to osv.dev. It never sends code.
--offlineskips it. The report lists it as disabled.
actionlint
- Version: 1.7.7.
- Runs when: a
.ymlor.yamlfile under.github/workflows/changed. - Needs: nothing. 2.0 MB on Apple Silicon, 2.1 MB on Linux x64.
- Sends: nothing.
hadolint
- Version: 2.15.1.
- Runs when: a Dockerfile changed:
Dockerfile,Dockerfile.<name>or<name>.dockerfile. - Needs: nothing. 102.6 MB on Apple Silicon, 55.7 MB on Linux x64.
- Sends: nothing.
shellcheck
- Version: 0.10.0.
- Runs when: a
.shor.bashfile changed. - Needs:
xzto unpack the download. 7.2 MB on Apple Silicon, 2.4 MB on Linux x64. - Sends: nothing.
golangci-lint
- Version: 2.12.2. Its name in
.openqodex.yamlisgolangci. - Runs when: a
.gofile changed. It checks the packages that hold the changed files. - Needs: Go on your
PATH. 14.4 MB on Apple Silicon, 15.0 MB on Linux x64. - Uses OpenQodex’s own settings, with gosec switched on. A
.golangci.ymlin the repo is not loaded. It never rewritesgo.modorgo.sum. - golangci-lint 2.12.2 is built with Go 1.26. With a newer Go on your PATH it cannot check the code. The report then lists golangci as failed, with the reason.
- Runs with the Go module proxy off. The modules the repo needs must already be in your Go module cache. Nothing is downloaded.
- Sends: nothing.
brakeman
- Version: 6.2.1.
- Runs when: a Ruby or Rails file changed, and the repo has a
Gemfileand anapp/folder. The files are.rb,.rake,.gemspec,.erb,.haml,.slim,Gemfile,Rakefileandconfig.ru. - Needs: Ruby 2.7 or newer. It installs from RubyGems.
- Uses OpenQodex’s own settings. The repo’s brakeman config is not loaded.
- Sends: nothing.
- Licence: the Brakeman Public Use License, which is not an open source licence. OpenQodex does not bundle brakeman. It downloads brakeman at run time onto your machine. Read the licence before you use it, or switch it off with
scanners.disable: [brakeman].
rubocop
- Version: 1.69.2, with rubocop-rails 2.28.0 and rubocop-performance 1.23.0.
- Runs when: a
.rb,.rakeor.gemspecfile, aGemfileor aRakefilechanged. - Needs: Ruby 2.7 or newer. It installs from RubyGems.
- Uses OpenQodex’s own settings. A
.rubocop.ymlin the repo is not loaded, because it can load Ruby code. - Sends: nothing.
sqllint
- Version: part of OpenQodex.
- Runs when: a
.sqlfile changed. - Needs: nothing. It runs inside OpenQodex and downloads nothing.
- Checks Postgres migrations for common mistakes, such as a privileged function left callable by every role.
- Sends: nothing.
Choosing scanners
scanners.disablein.openqodex.yamlswitches built-in scanners off.--onlyand--skiponscanandreviewpick scanners for one run.custom-scannersexplains how to add any other scanner.