Blocks destructive SQL in pull requests, and shows the rule, the line and a suggested fix for each finding.
No account needed. Offline mode checks on the runner with Vericto's 42 standard rules: no sign-up, no API key, and no SQL leaves the runner.
on: pull_request
jobs:
vericto:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with: { fetch-depth: 0 }
- uses: vericto/check-sql@v1
with: { offline: true, upload-sarif: false }Save it as .github/workflows/vericto.yml. The action checks the *.sql
files the pull request changes: an unbounded DELETE or UPDATE is BLOCKED
and fails the job, and schema changes such as DROP TABLE are FLAGGED. The
findings appear in the log, the job summary and as annotations on the pull
request. To also send them to Code Scanning, see the
full setup.
Offline, each file reports its strongest finding at line 1. Online, with a Vericto workspace (API key or OIDC), every statement is reported at its own line and checked against your workspace's rules. See Offline and online.
The action wraps vericto check from
the Vericto CLI. It downloads a pinned CLI release, verifies its SHA-256 before
extracting it, runs the check and uploads the SARIF report.
- Works on Linux (x64, arm64), macOS (x64, arm64) and Windows (x64, arm64) runners.
- Checks only the
*.sqlfiles a PR changes by default, or the files you list. - Works without an account: offline, the CLI's built-in engine applies the standard rules on the runner, and no SQL leaves it.
- With an account, authenticates with an API key or with GitHub OIDC (no stored secret) and applies your workspace's rules.
- Exits with the CLI's code, so a block fails the build and an outage is not mistaken for a pass.
This workflow also uploads the findings to Code Scanning and runs only when a
pull request changes SQL. Add it as .github/workflows/vericto.yml:
name: Vericto SQL check
on:
pull_request:
paths: ["**/*.sql"]
permissions:
contents: read
security-events: write # upload SARIF to Code Scanning
actions: read # needed by the SARIF upload in private repositories
jobs:
vericto:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0 # full history, so the PR's changed files can be diffed
- uses: vericto/check-sql@v1
with:
offline: trueThat is the whole setup: no sign-up, no API key, no secret. The action checks
the *.sql files the PR changes with Vericto's standard rules (dialect
defaults to postgres), on the runner, and the findings show up on the PR. An
unbounded DELETE or UPDATE blocks; schema changes (DROP, ALTER, TRUNCATE)
are flagged. See Offline and online for what an
account adds.
Leaving out offline: true works too: with no credential configured, the
action checks offline on its own, with a warning that says so (see
Which mode a run uses).
Online, the action checks against your workspace's rules: your custom rules and overrides, business policies and sensitive columns, and every check is recorded in the dashboard.
- Create an API key with the
ci_dryrun:executescope in the Vericto dashboard (API keys). - Add it to the repository as a secret named
VERICTO_API_KEY(Settings, Secrets and variables, Actions). - In the workflow above, pass the key instead of
offline: true:
- uses: vericto/check-sql@v1
with:
api-key: ${{ secrets.VERICTO_API_KEY }}To make a missing secret fail the job instead of checking offline, add
offline: false.
With OIDC, the job proves its identity to Vericto with a short-lived GitHub
token instead of a stored key. The CLI exchanges the token for a key scoped to
ci_dryrun:execute, keeps it in memory for the run and never writes it to disk.
- In the Vericto dashboard, add a trust policy to the workspace: issuer
https://token.actions.githubusercontent.com, audienceverictoand a subject pattern such asrepo:my-org/*. - Give the job
id-token: writeand pass the workspace ID:
permissions:
contents: read
security-events: write
actions: read
id-token: write # mint the OIDC token
jobs:
vericto:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: vericto/check-sql@v1
with:
oidc: true
workspace: ws_123workspace can also come from workspace_id in .vericto.toml.
Offline (offline: true, or no credential) |
Online (api-key or oidc) |
|
|---|---|---|
| Account, key | none | a Vericto workspace; API key or OIDC |
| Network | none: no SQL leaves the runner | the selected SQL goes to your workspace, sanitized if it says so |
| Rules | the CLI's standard rules (42 in CLI 2.0.0), at their default severities | your workspace's rules: the standard rules with your overrides, plus custom rules |
| Business policies, sensitive columns, masking | no | yes |
| Granularity | one result per file, with its strongest finding, at line 1 | one result per statement, at its line |
| Check history and audit trail in the dashboard | no record anywhere | every check recorded, with the commit, run and actor |
| Baselines | inline -- vericto:ignore[...] works; a baseline recorded online (vericto baseline needs an account) does not match offline findings |
yes |
| Metered | no | counts against the plan's monthly CLI allowance |
| Annotations, job summary, SARIF, outputs | yes | yes |
Offline is a baseline gate ("is this SQL obviously dangerous?"), not your
workspace's policy and not evidence that a check took place. Every offline
result says so: the CLI titles its annotations Vericto (offline), the SARIF
and JSON reports carry "mode": "offline" and the engine version, the job
summary has a Mode row, and the mode output is offline. Offline needs
CLI 1.9.0 or later (1.11.0 on Windows runners); the default, 2.0.0, has it.
The CLI's offline mode
has the details.
| Credential configured | offline: auto (default) |
offline: true |
offline: false |
|---|---|---|---|
| none | offline, with a warning annotation | offline | exit 3 |
api-key input |
online | exit 2 (set one or the other) | online |
VERICTO_API_KEY on the job only |
online | offline; the key is not used (notice) | online |
oidc: true |
online | exit 2 (set one or the other) | online |
- A configured credential never falls back to offline. A key that is rejected is exit 3 and an API that cannot be reached is exit 4, as before, so a CI gate never weakens silently.
- Only "no credential at all" checks offline on its own, and it says so
with a warning annotation, the
Moderow in the job summary and themodeoutput. The action cannot tell an empty secret from a secret that was never set:api-key: ${{ secrets.VERICTO_API_KEY }}with the secret missing, or a pull request from a fork (forks get no secrets), checks offline too. Setoffline: falsewhere that must fail the job instead. api-url,timeoutandworkspaceare not used offline (a notice says so). AVERICTO_OFFLINEvariable set on the job never chooses the mode: with a credential it is ignored, with a warning.
| Input | Default | Description |
|---|---|---|
offline |
auto |
true: check offline with the standard rules, no account. false: always online; no credential is exit 3. auto: online with a credential, offline (with a warning) without one. See Which mode a run uses. |
api-key |
Vericto API key (vtro_...), from a secret. Not used with oidc: true or offline: true. Falls back to a VERICTO_API_KEY env var set on the job. |
|
oidc |
false |
Authenticate with GitHub OIDC. Needs id-token: write. |
workspace |
Workspace ID for OIDC. Falls back to VERICTO_WORKSPACE_ID, then .vericto.toml. |
|
files |
Paths or globs (*, ?, [...], **), separated by spaces or newlines, relative to working-directory. A directory means every *.sql under it. Empty: check changed files. |
|
changed |
true when files is empty |
Check only the *.sql files changed against the base (see Changed files). |
since |
Base ref for the changed-files diff, e.g. origin/main. Implies changed. |
|
dialect |
postgres | postgres, mysql, oracle or mssql. Empty uses default_dialect from .vericto.toml, else postgres. |
baseline |
Baseline file to apply (as written by vericto baseline, by default .vericto-baseline.json). Falls back to .vericto.toml. |
|
format |
sarif |
sarif, json, text, gitlab-codequality or gitlab-sast. |
upload-sarif |
true |
Upload the SARIF report to Code Scanning (only with format: sarif). |
api-url |
CLI default | Vericto API base URL (https://api.vericto.com). |
timeout |
CLI default (30) | Per-request timeout, in seconds. |
cli-version |
2.0.0 |
Vericto CLI release to install. Pinned per action release; latest is rejected. See Sanitized mode before pinning an older one; Windows ARM64 runners need 1.11.0 or later. |
working-directory |
. |
Where the check runs (where .vericto.toml lives). With changed, it must be the root of the checkout. |
fail_on (which severity fails the run) is read from .vericto.toml; the
default is to fail only on BLOCKED findings. See the
CLI's project config.
| Output | Description |
|---|---|
exit-code |
The CLI's exit code (table below). |
result |
pass, warn (passed, with findings that don't fail the run) or fail. |
mode |
online (your workspace's rules) or offline (the standard rules); empty if the action failed before choosing. |
sarif-file |
Path to the SARIF report; empty if none was written. |
report-file |
Path to the report for any machine format; empty for text. |
blocked, flagged, monitored, parse-errors |
Finding counts, for the sarif and json formats. |
| Exit code | Meaning |
|---|---|
0 |
Nothing at or above fail_on. |
1 |
A finding at or above fail_on. |
2 |
Usage error: bad input, unreadable file, no base ref for changed. |
3 |
Authentication or plan error: missing (with offline: false) or invalid key, OIDC not configured, plan not entitled, monthly allowance used up. Online only. |
4 |
Backend or network error, including a workspace config that can't be read. No verdict, and no SQL is sent in that case. Online only. |
A non-zero code fails the step, and the job with it, unless you set
continue-on-error: true and decide from exit-code.
| Permission | Why |
|---|---|
contents: read |
Check out the code. |
security-events: write |
Upload SARIF to Code Scanning (upload-sarif: true). |
actions: read |
Required by the SARIF upload in private repositories. |
id-token: write |
OIDC only. Offline needs none of the Vericto ones. |
Code Scanning is available on public repositories, and on private ones with
GitHub Advanced Security (GitHub Code Security). Without it, set
upload-sarif: false: the check, the log and the job summary still work.
on:
pull_request:
paths: ["**/*.sql"]
push:
branches: [main]
paths: ["**/*.sql"]
# ...
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: vericto/check-sql@v1
with:
api-key: ${{ secrets.VERICTO_API_KEY }}
dialect: mysql - uses: vericto/check-sql@v1
with:
api-key: ${{ secrets.VERICTO_API_KEY }}
files: |
db/migrations/**/*.sql
reports/monthly.sqlfetch-depth: 0 is not needed when you list files. A pattern that matches no
SQL file fails with exit code 2, so a typo can't turn into a silent pass.
Record today's findings once, commit the baseline, and only new findings fail:
vericto baseline db/migrations/*.sql # writes .vericto-baseline.json
git add .vericto-baseline.json - uses: vericto/check-sql@v1
with:
api-key: ${{ secrets.VERICTO_API_KEY }}
baseline: .vericto-baseline.jsonBaselined findings are still reported (result: warn); they just don't fail
the run. A single statement can also be suppressed inline with
-- vericto:ignore[VERICTO-001] reason. vericto baseline records online
findings and needs an account; offline, use the inline suppression.
- uses: vericto/check-sql@v1
with:
api-key: ${{ secrets.VERICTO_API_KEY }}
working-directory: services/billing
files: migrationsReport paths are rewritten relative to the repository root, so annotations land on the right files.
- id: vericto
uses: vericto/check-sql@v1
continue-on-error: true
with:
api-key: ${{ secrets.VERICTO_API_KEY }}
- if: steps.vericto.outputs.result != 'pass'
run: echo "Vericto: ${{ steps.vericto.outputs.blocked }} blocked, ${{ steps.vericto.outputs.flagged }} flagged"This action is for GitHub Actions. On GitLab CI, run the CLI directly with
--format gitlab-codequality; the CLI README
has a ready-made job.
With changed (the default when files is empty), the CLI checks the *.sql
files that differ from a base, excluding deleted files. The base is:
since, when set;- on
pull_request, the PR's base branch (origin/<base>); - on
merge_group, the queue's base commit; - on
push, the commit before the push; - otherwise, the repository's default branch (
origin/<default>).
The diff needs the base commit, so check out with fetch-depth: 0. When no SQL
changed, the check passes and no SQL is sent.
could not determine a base reforgit diff ... failed(exit 2): the checkout is shallow or lacks the base branch. Usefetch-depth: 0, or setsince.changed must run from the root of the git checkout: git reports changed paths from the repository root. Run from the root, or listfiles.No Vericto credential is configured, so this run checks offline(warning): noapi-key, noVERICTO_API_KEYand nooidc, so the action checked with the standard rules. Setoffline: trueif that is what you want, or check the secret's name and that the event gets secrets (fork pull requests don't).offline: falsemakes this case fail with exit 3.- Exit 3: the key is missing (with
offline: false), invalid or lacksci_dryrun:execute; the OIDC trust policy doesn't match the repository; or the plan's monthly CLI allowance is used up.vericto doctorshows which. oidc: true needs 'permissions: id-token: write': add the permission to the job. Pull requests from forks don't get OIDC tokens or secrets.VERICTO_OFFLINE is set on the job; ignored here: with a credential, the action checks online; only itsofflineinput chooses offline mode (see Which mode a run uses). SetVERICTO_OFFLINEonly on the steps that run the CLI themselves.offline mode needs cli-version 1.9.0 or later(or 1.11.0 on Windows runners): the pinnedcli-versionpredates offline mode. Leavecli-versionat its default, or pin a newer one.Windows ARM64 runners need cli-version 1.11.0 or later(exit 2): CLI releases before 1.11.0 have no Windows ARM64 build. Pin 1.11.0 or later, or leavecli-versionat its default.- Exit 4: the API could not be reached, or the workspace config could not
be read. Corporate TLS proxies: set
VERICTO_CA_BUNDLE(a PEM path) in the job'senv. - SARIF upload fails with "Advanced Security must be enabled" or "Resource
not accessible by integration": Code Scanning is not available on this
repository, or the job lacks
security-events: write(fork PRs never have it). Setupload-sarif: falsethere.
- Checksum verification. The CLI is downloaded from the
vericto-cli release that
cli-versionpins, never fromlatest. Its SHA-256 is verified against the release's.sha256file before the archive is extracted; a mismatch stops the action. A cached download is re-verified on every run, and the binary onPATHis always extracted from the verified archive. - Build attestation (advisory). When the GitHub CLI is available, the
action also runs
gh attestation verifyagainst the release's Sigstore build provenance. If that can't run (nogh, no network to the attestation API) or doesn't pass, the action logs a warning and continues: the checksum is the gate. - No secrets on the command line. The API key reaches the CLI only through
the
VERICTO_API_KEYenvironment variable, is masked in the log, and the CLI never prints it. Pass it fromsecrets.*so the runner masks it from the start. - No shell injection. No input is interpolated into a script: each one is passed through an environment variable, validated, and handed to the CLI as a single argument.
- Pinned dependencies. Every action this action uses is pinned by commit
SHA. You can pin this action the same way:
uses: vericto/check-sql@<full commit SHA> # v1.4.0.
Report vulnerabilities as described in SECURITY.md.
Offline, nothing is sent: the CLI makes no request of any kind, to Vericto or anyone else, and evaluates on the runner.
Online, checking SQL means sending it to your Vericto workspace, which evaluates it with your rules. What is sent, per the CLI design:
- Only the files selected for the check (the changed
*.sqlfiles, orfiles) and their paths, to your workspace's API only, over TLS (https://api.vericto.comunless you setapi-url). No other file in the repository is sent. - Sanitized when your workspace says so. Before sending any SQL, the CLI
reads the workspace's telemetry mode. In
sanitizedmode it replaces literal values with placeholders ($1,$2, ...) on the runner, so raw values never leave it. Sanitization is a workspace setting, not a per-run flag. It needs CLI 1.8.2 or later (see below). - Fail closed. If the workspace config can't be read, the CLI sends no SQL and exits with code 4.
- Run metadata for the audit trail: commit SHA, ref, CI provider, run URL and the actor's username. Never a credential.
- Not kept by the CLI. It does not persist the SQL beyond the request. The report it writes can quote short previews and suggested fixes, so treat it like the SQL itself.
See Telemetry & privacy.
Since action 1.0.3 the action installs CLI 1.8.2 by default (1.0.0 to 1.0.2
installed 1.7.1). Before 1.8.2, the CLI's sanitizer replaced only the plain
literals: in some dialect-specific cases (Snowflake and MySQL backslash
escapes, MySQL double-quoted strings, Oracle q'[...]' strings, dollar-quoted
strings, comments a dialect reads differently, prefixed literals and numbers,
unterminated quotes) part of a literal was sent as written. In 1.8.2 the
sanitized telemetry no longer leaks literal fragments: the sanitizer ends
every literal where the dialect's own lexer ends it, and replaces whatever it
cannot read with certainty. See the
CLI changelog for 1.8.2.
Nothing changes for a workspace in raw mode. If you pin cli-version, your
pin still applies; with a sanitized workspace, pin 1.8.2 or later. The
default was CLI 1.12.0 from action 1.2.0 to 1.3.0, and is CLI 2.0.0 since
action 1.4.0.
Releases follow Semantic Versioning. The major tag
(v1) moves to each compatible release, the usual convention for GitHub
Actions; @v1.4.0 or a commit SHA stays fixed. Each action release pins a
CLI version, and a CLI bump ships as a new action release.
The scripts in scripts/ have offline unit tests (bash 3.2+, git and jq),
run in CI on Linux and macOS:
for t in lib resolve verify-checksum install check; do bash "test/$t-test.sh"; doneThey use local fixtures only: test/install-test.sh serves the release
download from file:// through a curl stand-in, and test/check-test.sh
runs check.sh against a stand-in CLI (test/fixtures/fake-cli/vericto). A
case marked xfail is a known bug, kept visible until it is fixed.
test/checksum-test.sh VERSION checks the same gate against the real release
asset and needs the network.
See CONTRIBUTING.md for the checks CI runs, the rules for the scripts, and how releases are cut.
Open source under the Apache License 2.0 (SPDX Apache-2.0) since
1.1.0. Versions 1.0.3 and earlier were released under the Elastic License 2.0
and remain under it. Copyright 2026 Vericto S.A.S.; see NOTICE. The
license grants no right to the Vericto name or logo: see
TRADEMARKS.md.
The Vericto CLI that the action downloads and runs is a separate program under
its own license. From CLI 2.0.0 it is open source under the GNU Affero General
Public License, version 3 only (AGPL-3.0-only), and free to use in production,
including commercially; a commercial license from Vericto S.A.S.
(legal@vericto.com) is available for closed or
embedded use. Earlier CLI releases keep the license they were released with:
the Functional Source License (FSL-1.1-ALv2) for 1.10.0 to 1.13.3, and the
Elastic License 2.0 for 1.9.1 and earlier. The default cli-version, 2.0.0,
is AGPL-3.0-only (action 1.2.0 to 1.3.0 defaulted to 1.12.0, under
FSL-1.1-ALv2). See its
LICENSING.md.
The Vericto service it calls is offered under its own
terms.
Vericto SQL Check es una GitHub Action que valida el SQL de sus pull requests (migraciones, scripts, consultas generadas) contra las reglas de su espacio de trabajo de Vericto antes de que se ejecute. Los hallazgos aparecen como anotaciones de Code Scanning en el PR y una sentencia bloqueada hace fallar el job.
Uso básico, sin cuenta ni clave de API (modo offline, con las reglas estándar):
permissions:
contents: read
security-events: write
actions: read
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: vericto/check-sql@v1
with:
offline: trueCon una cuenta de Vericto, guarde una clave de API en el secreto
VERICTO_API_KEY y páselo en lugar de offline: true
(api-key: ${{ secrets.VERICTO_API_KEY }}) para validar contra las reglas de
su espacio de trabajo.
- Por defecto se revisan solo los archivos
*.sqlque cambian en el PR. Para revisar archivos concretos, indíquelos enfiles. - En modo offline no se envía ningún SQL: el motor incluido en el CLI aplica
las reglas estándar en el runner. Una cuenta agrega sus reglas
personalizadas, políticas de negocio, columnas sensibles y el historial y la
auditoría en el panel. Sin ninguna credencial configurada, la acción valida
offline con una advertencia; con
offline: false, falla con código 3. Una credencial configurada nunca pasa a offline si la API falla. - Para no guardar una clave, use OIDC:
oidc: true,workspace: ws_...y el permisoid-token: write. - La acción descarga una versión fija del CLI (2.0.0 por defecto) y verifica su SHA-256 antes de extraerlo. La clave de API se pasa solo por variable de entorno y nunca aparece en la línea de comandos.
- En modo online, el SQL seleccionado se envía a su espacio de trabajo para
evaluarlo. Si el espacio está en modo
sanitized, los valores literales se reemplazan en el runner antes del envío.
Licencia: código abierto bajo la Apache License 2.0 desde 1.1.0. Las versiones 1.0.3 y anteriores se publicaron bajo la Elastic License 2.0 y siguen bajo ella. La CLI de Vericto que la action descarga tiene su propia licencia: desde la 2.0.0 es código abierto bajo la AGPL-3.0-only, de uso libre en producción, también comercial, con una licencia comercial de Vericto S.A.S. (legal@vericto.com) para uso cerrado o embebido. La 2.0.0, que instala por defecto, es AGPL-3.0-only. Las versiones anteriores conservan su licencia (FSL-1.1-ALv2 de la 1.10.0 a la 1.13.3, incluida la 1.12.0 que instalaban por defecto las versiones 1.2.0 a 1.3.0 de la acción; Elastic License 2.0 hasta la 1.9.1). La licencia no otorga derechos sobre la marca Vericto (TRADEMARKS.md).
La documentación completa está en inglés, más arriba, y en vericto.com/docs.
