Max Total + Snyk Collector
Enforce Max Total using data collected by Snyk Collector. Automatically check security and compliance standards on every PR.
How Snyk Collector Powers This Guardrail
The Snyk Collector gathers metadata from your systems. This data flows into Lunar's Component JSON, where the Max Total guardrail evaluates it against your standards.
When enabled, this check runs automatically on every PR and in AI coding workflows, providing real-time enforcement with actionable feedback.
Quick Start Configuration
Add both the collector and policy to your lunar-config.yml to enable this guardrail.
# Step 1: Enable the Snyk Collector
collectors:
- uses: github://earthly/lunar-lib/collectors/snyk@v1.0.5
# with: ...
# Step 2: Enable the Container Scan Guardrails
policies:
- uses: github://earthly/lunar-lib/policies/container-scan@v1.0.5
include: [max-total]
# with: ...
What Snyk Collector Collects
This collector gathers the following data that the Max Total guardrail evaluates.
github-app
Detects Snyk GitHub App scans on pull requests by querying GitHub commit status API. Waits for scan completion and captures results. Categorizes by scan type (Open Source, Code, Container, IaC).
running-in-prs
Proves Snyk is running on PRs by querying Lunar Hub for Snyk data from recent PRs. Used on the default branch to provide compliance proof that PR scanning is happening (since Snyk GitHub App only posts checks on PRs, not directly on the default branch).
cli
Detects Snyk CLI executions in CI pipelines. Captures the command and exit code, then categorizes by subcommand (test, code, container, iac).
Example Data Flow
Here's an example of the data that Snyk Collector writes to the Component JSON, which Max Total then evaluates.
{
"sca": {
"running_in_prs": true,
"source": {
"tool": "snyk",
"version": "1.1200.0",
"integration": "ci"
},
"vulnerabilities": {
"critical": 1,
"high": 1,
"medium": 1,
"low": 0,
"total": 3
},
"findings": [
{
"severity": "critical",
"package": "minimist",
"version": "1.2.0",
"ecosystem": "npm",
"cve": "CVE-2021-44906",
"snyk_id": "SNYK-JS-MINIMIST-2",
"title": "Prototype Pollution",
"fix_version": "1.2.6",
"fixable": true
}
],
"summary": {
"has_critical": true,
"has_high": true,
"has_medium": true,
"has_low": false,
"all_fixable": false
},
"native": {
"snyk": {
"github_app": {
"state": "success",
"context": "security/snyk",
"target_url": "https://app.snyk.io/..."
},
"cicd": {
"cmds": [
{"cmd": "snyk test --all-projects --json-file-output=snyk-sca.json", "version": "1.1200.0"}
],
"raw": {
"vulnerabilities": ["...full Snyk JSON output..."],
"ok": false
}
}
}
}
}
}
Configuration Options
Snyk Collector Inputs
| Input | Required | Default | Description |
|---|---|---|---|
github_app |
Required | — | GitHub App to mint API tokens from, by its name in `lunar github-app add` (e.g. `lunar-lib`). Unset, the plugin uses the GH_TOKEN secret without calling the Hub; set, the secret is the fallback when the App can't mint a token. |
github_app_only |
Optional |
false
|
Fail instead of falling back to the GH_TOKEN secret, to check the `github_app` App works before the secret is removed. |
Container Scan Guardrails Inputs
| Input | Required | Default | Description |
|---|---|---|---|
min_severity |
Optional |
high
|
Minimum severity to fail on (critical, high, medium, low) |
ignore_unfixable |
Optional |
false
|
Only fail max-severity on findings that have a fix available. Unfixable findings are still reported in the component JSON. |
exempt_findings |
Required | — | Vulnerabilities `max-severity` ignores because the risk was reviewed and accepted. Entries are `<id> <package>@<version>`, optionally followed by image globs, separated by newlines or commas: ```yaml with: exempt_findings: | # bundled inside a vendor tool that hasn't shipped urllib3 2.8.0 CVE-2026-97687 urllib3@2.7.0 registry.example.com/tools:* ``` Id, package and version must match the finding exactly (the id ignores case), so an entry stops matching once the package is upgraded. With globs, only findings in a matching image are exempt, and a finding with no recorded image never is. `#` comments are ignored. Exempt findings stay in the component JSON. The check still fails on the rest, and resolves to `skip`, naming the entries that matched, only when every finding that would have failed was exempt. An entry that cannot be parsed fails the check without exempting anything. `max-total` ignores this input. Approved records in `.compliance.vulnerability_exemptions.records[]` (written by the `vulnerability-exemptions` collector) also exempt findings that have no fix, read at run time, alongside this input. |
max_total_threshold |
Required | — | Maximum total findings allowed (must be configured) |
Ready to Automate Your Standards?
See how Lunar can turn your AGENTS.md, engineering wiki, compliance docs, or postmortem action items into automated guardrails with our 300+ built-in guardrails.