When Snyk code scanning finds a vulnerability inside a GitHub Actions pipeline, that finding doesn't magically appear in the repository's Security tab — it travels through a specific, well-documented file format called SARIF. A developer runs snyk code test --sarif-file-output=snyk-code.sarif (or the equivalent flag on snyk test / snyk iac test), the CLI writes a JSON document that conforms to the OASIS SARIF 2.1.0 schema, and a separate step — usually github/codeql-action/upload-sarif@v3 — ships that file to GitHub, which parses it into annotated code-scanning alerts. Nothing about this is proprietary or hidden: SARIF is an open, versioned standard, and GitHub publishes exactly which fields it reads. This post walks through that pipeline mechanically — what SARIF is, how the Snyk CLI builds it, what a single result object contains, and where teams commonly hit the format's hard limits — as a technical reference for anyone wiring Snyk into a GitHub Actions workflow.
What is SARIF, and why does GitHub code scanning require it?
SARIF (Static Analysis Results Interchange Format) is an OASIS standard, currently at version 2.1.0, ratified in 2020 to give static analysis tools a common JSON schema for reporting findings instead of each vendor inventing its own. GitHub's code scanning feature — the engine behind the repository "Security" tab — only ingests results in this format (or converts them to it internally, in the case of CodeQL). That means any third-party scanner, Snyk included, has to emit SARIF rather than its native output if it wants findings to show up as inline pull request annotations, line-level alerts, and dismissible entries in the Security tab. The schema defines a runs array, each containing a tool object (which tool produced the results and which rules it can trigger) and a results array (the actual findings, each tied back to a rule ID and a source location). Because the schema is public, GitHub's parser and Snyk's generator only need to agree on the same spec — they don't need any special integration contract beyond it.
How does the Snyk CLI actually generate the SARIF file?
The Snyk CLI generates SARIF by running its normal scan and then serializing the results into the schema instead of (or in addition to) its default human-readable or JSON output. For Snyk Code, the documented invocation is snyk code test --sarif to print SARIF to stdout, or snyk code test --sarif-file-output=<path> to write it directly to a file — the latter is the form almost every CI example uses, since it decouples the scan step from the upload step. Snyk's official GitHub Actions, published under the snyk/actions namespace (for example snyk/actions/node, snyk/actions/python, snyk/actions/docker), accept the same CLI arguments through an args input, so a workflow step typically looks like args: --sarif-file-output=snyk.sarif combined with continue-on-error: true, since a scan that finds vulnerabilities exits non-zero and would otherwise stop the pipeline before the upload step runs. This snyk/actions namespace is the backbone of most turnkey Snyk integration setups in GitHub Actions — teams rarely hand-roll the CLI invocation once the maintained action covers it.
What does a single SARIF result from Snyk contain?
Each entry in the results array carries a ruleId, a level (error, warning, or note), a message.text description, and a locations array pointing to the exact file path and line range where the issue was found — for a SAST finding this might be the specific line in a JavaScript file where untrusted input reaches a dangerous sink; for a dependency finding it's typically the manifest file (package.json, pom.xml) that pulled in the vulnerable package. The corresponding entry in tool.driver.rules supplies the metadata GitHub renders as context: a name, a fullDescription, a helpUri (Snyk populates this with a link back to its vulnerability database, e.g. security.snyk.io/vuln/SNYK-JS-...), and a properties object carrying a security-severity score. That score is a CVSS-style number from 0.0 to 10.0, and GitHub uses documented thresholds to bucket it into the Critical, High, Medium, and Low labels shown in the UI — roughly 9.0+ as Critical, 7.0–8.9 as High, 4.0–6.9 as Medium, and below 4.0 as Low.
How does the SARIF file get from the CLI into GitHub's Security tab?
It gets there through a dedicated upload step, not automatically — the CLI only produces the file, it doesn't talk to GitHub's API on its own. The standard pattern is GitHub's own github/codeql-action/upload-sarif action, referenced by a workflow step with a sarif_file input pointing at the path the CLI just wrote (e.g. sarif_file: snyk.sarif). That action reads the file, validates it against the SARIF schema, and calls GitHub's code scanning API to attach the results to the current commit or pull request. A category input can be set when multiple SARIF-producing tools run in the same workflow, so GitHub doesn't overwrite one tool's alerts with another's on the next run. Repositories need GitHub Advanced Security enabled (for private repos) or can use code scanning natively on public repos, and the workflow's job needs security-events: write permission or the upload step fails with an authorization error before it ever reaches GitHub's parser. Get those two prerequisites right and the rest of a Snyk GitHub integration is just wiring — the CLI, the action, and the permission scope are the only moving parts.
What limits does GitHub place on SARIF uploads, and where do teams hit them?
GitHub documents hard caps on what a single SARIF upload can contain: the file must be under 10 MB (or under 10 MB after gzip compression when sent via the API directly), and a single upload is capped at 5,000 results, with only the first 5,000 processed if a scan exceeds it. Teams with large monorepos or a first-time Snyk Open Source scan against a dependency tree with years of accumulated transitive vulnerabilities can realistically produce SARIF output that exceeds one or both limits, which silently truncates the alerts that show up in the Security tab rather than failing the workflow outright. GitHub also only accepts SARIF conforming to the 2.1.0 schema (or the JSON schema draft it validates against), so a malformed results object — a missing ruleId reference, for instance — causes the entire upload to be rejected rather than partially processed. These are documented, provider-side constraints on the receiving end (GitHub's API), not something the Snyk CLI can configure around; they simply need to be planned for when scoping which projects or branches run SARIF-producing scans in CI.
How Safeguard Helps
Understanding the SARIF mechanics matters because most engineering organizations aren't running just one scanner — Snyk for dependencies, a separate SAST tool, container image scanning, IaC checks — and each one produces its own SARIF file, its own severity scale, and its own upload step competing for the same Security tab. Safeguard is built for that reality: it ingests SARIF and other native scanner outputs across the software supply chain, normalizes severity and provenance across tools, and correlates findings against the actual build and deployment path a package took, rather than treating each scanner's alert list as a disconnected feed. That gives security teams a single, policy-driven view of supply chain risk — dependency vulnerabilities, code-level findings, and artifact provenance together — instead of reconciling five different SARIF uploads by hand across repositories. For teams already relying on Snyk's SARIF output in GitHub Actions, Safeguard sits alongside that pipeline to add the cross-tool correlation, historical tracking, and policy enforcement that a single scanner's SARIF file, by design, doesn't provide on its own. (Everything above is specific to GitHub's code scanning API; a Snyk GitLab integration follows the same SARIF-generation step from the CLI but uploads through GitLab's own security report ingestion instead of codeql-action/upload-sarif, so the upload mechanics — not the SARIF file itself — are what differ.)