Skip to content

Suppression

A suppression rule: findings that match its scope are suppressed, now and in every later scan, until it expires. Fields, YAML, HCL and CLI samples, and how apply treats it.

Checked against config-schemas@v1.15.0, terraform-provider-resolve@82cb23c, cli@v4.9.1

A suppression rule: findings that match its scope are suppressed, now and in every later scan, until it expires. Every apply writes the suppression audit. Rules created from a VexSource are owned by that source and cannot be declared here.

apiVersion vulnetix.com/v1
kind Suppression
Group Suppression
Status Served. The config engine plans and applies it.
Objects per tenant many, keyed by metadata.name
Token and role An owner or admin session, or a vmt_ config management token with the owner or admin role that lists Suppression in its kinds. See Management tokens.
CEL fields spec.when (finding): see CEL rule expressions
Terraform resource vulnetix_suppression, imported by name (see Terraform and OpenTofu)
CLI vulnetix config apply, CLI v3.157.0 and later.
Pinned schema v1.15.0/Suppression.schema.json
Newest schema latest/Suppression.schema.json
First released in v1.1.0
Print the built-in copy vulnetix config schema Suppression

Minimal

Only the fields the kind requires. From examples/Suppression/minimal.yaml.

YAML

apiVersion: vulnetix.com/v1
kind: Suppression
metadata:
  name: lodash-prototype-pollution
spec:
  type: risk_accepted
  scope:
    rule: CVE-2021-23337

HCL (resource vulnetix_suppression)

# Only the arguments the kind requires. From config-schemas examples/Suppression/minimal.yaml.

resource "vulnetix_suppression" "lodash_prototype_pollution" {
  name = "lodash-prototype-pollution"
  scope = {
    rule = "CVE-2021-23337"
  }
  type = "risk_accepted"
}

CLI (applies it)

export VULNETIX_CONFIG_TOKEN=vmt_...   # a config management token
vulnetix config apply -f - --manager gitops:acme/platform --auto-approve <<'EOF'
apiVersion: vulnetix.com/v1
kind: Suppression
metadata:
  name: lodash-prototype-pollution
spec:
  type: risk_accepted
  scope:
    rule: CVE-2021-23337
EOF

Advanced

Every field the kind supports, with a when expression where it takes one. From examples/Suppression/advanced.yaml.

YAML

apiVersion: vulnetix.com/v1
kind: Suppression
metadata:
  name: lodash-template-not-reachable
  labels:
    team: payments
  annotations:
    ticket: https://jira.example.com/browse/SEC-1234
spec:
  type: false_positive
  reason: lodash.template is never called with user input; the build only renders static templates.
  justification: vulnerable_code_not_in_execute_path
  scope:
    category: sca
    rule: CVE-2021-23337
    target: pkg:npm/lodash
    purl: pkg:npm/lodash@4.17.20
    path: web/package-lock.json
    line: 1204
    lineRange: 1204-1210
    repository: acme/storefront
    branch: main
  expires: 2027-06-30T00:00:00Z
  when: severity != 'critical' && !kev && repo == 'acme/storefront'

HCL (resource vulnetix_suppression)

# Every argument the kind supports. From config-schemas examples/Suppression/advanced.yaml.

resource "vulnetix_suppression" "lodash_template_not_reachable" {
  name          = "lodash-template-not-reachable"
  expires       = "2027-06-30T00:00:00Z"
  justification = "vulnerable_code_not_in_execute_path"
  reason        = "lodash.template is never called with user input; the build only renders static templates."
  scope = {
    branch     = "main"
    category   = "sca"
    line       = 1204
    line_range = "1204-1210"
    path       = "web/package-lock.json"
    purl       = "pkg:npm/lodash@4.17.20"
    repository = "acme/storefront"
    rule       = "CVE-2021-23337"
    target     = "pkg:npm/lodash"
  }
  type = "false_positive"
  when = "severity != 'critical' && !kev && repo == 'acme/storefront'"
  labels = {
    team = "payments"
  }
  annotations = {
    ticket = "https://jira.example.com/browse/SEC-1234"
  }
}

CLI (applies it)

export VULNETIX_CONFIG_TOKEN=vmt_...   # a config management token
vulnetix config apply -f - --manager gitops:acme/platform --auto-approve <<'EOF'
apiVersion: vulnetix.com/v1
kind: Suppression
metadata:
  name: lodash-template-not-reachable
  labels:
    team: payments
  annotations:
    ticket: https://jira.example.com/browse/SEC-1234
spec:
  type: false_positive
  reason: lodash.template is never called with user input; the build only renders static templates.
  justification: vulnerable_code_not_in_execute_path
  scope:
    category: sca
    rule: CVE-2021-23337
    target: pkg:npm/lodash
    purl: pkg:npm/lodash@4.17.20
    path: web/package-lock.json
    line: 1204
    lineRange: 1204-1210
    repository: acme/storefront
    branch: main
  expires: 2027-06-30T00:00:00Z
  when: severity != 'critical' && !kev && repo == 'acme/storefront'
EOF

Fields

Paths use dots for nesting and [] for the items of a list. Required means required whenever the parent object is present. A default is what the server uses when the field is left out.

Field Type Required Default Allowed values Description
apiVersion string yes exactly vulnetix.com/v1 The document format version. Every kind in this release is vulnetix.com/v1.
kind string yes exactly Suppression Always Suppression.
metadata object yes no other keys
metadata.name string yes pattern ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$ The object’s name, unique per kind within a tenant. It is the natural key: plan, apply, export and the Terraform provider all address an object by kind and name.
metadata.org string no format uuid The tenant (organization UUID) the document belongs to. When set, plan and apply refuse to run against any other tenant.
metadata.labels object no map of string to string (length 0 to 256); keys match ^[a-z0-9]([a-z0-9._/-]{0,61}[a-z0-9])?$ Free key/value labels. Stored with the object, never interpreted by the server.
metadata.annotations object no map of string to string (length 0 to 4096) Free key/value notes for people and tools, such as a ticket link.
spec object yes no other keys
spec.type string yes false_positive, wont_fix, risk_accepted, mitigated, deferred The decision: false_positive (the finding is wrong), wont_fix, risk_accepted, mitigated (a control outside the code covers it) or deferred.
spec.reason string no Why, for the people who review suppressions.
spec.justification string no component_not_present, vulnerable_code_not_present, vulnerable_code_not_in_execute_path, vulnerable_code_cannot_be_controlled_by_adversary, inline_mitigations_already_exist Why the product is not affected, in the OpenVEX vocabulary, for VEX documents minted from this rule.
spec.scope object yes no other keys What the rule matches. It must name at least one of rule, target or path; a rule that names none would match everything. Every field given must match.
spec.scope.category string no sast, secrets, iac, container, sca, license, malware, crypto, ai The finding category. crypto and ai are inventory components (a CBOM algorithm, certificate, key or library; an AIBOM agent, SDK, model or service), which match on target.
spec.scope.rule string no length 1 to any The vulnerability or rule id: a CVE or other advisory id, or a SAST, IaC or secrets rule id.
spec.scope.target string no length 1 to any An inventory component’s identity: an algorithm SPDX id, a certificate subject, a purl or a model name.
spec.scope.purl string no pattern ^pkg:[a-z][a-z0-9.+-]*/.+ Only findings in this package. Without a version, every version.
spec.scope.path string no length 1 to any A file path, relative to the repository root.
spec.scope.line integer no >= 1 A line in path.
spec.scope.lineRange string no length 1 to any A range of lines in path.
spec.scope.repository string no pattern ^[^\s/]+(/[^\s/]+)+$ A repository by its full name, owner/name as the forge shows it. Nested groups (group/subgroup/name) are allowed.
spec.scope.branch string no length 1 to any
spec.expires string no format date-time, or format date When the rule stops applying. Left out, it never expires; reports flag it once it goes unreviewed for the RemediationPolicy suppressionReviewMaxAgeDays.
spec.when string no length 1 to 4096 An extra condition a finding must meet, over the finding variables. It fails open: a finding the expression fails on is not suppressed, and a rule that cannot be evaluated covers nothing and is logged.

Rules

Conditions the schema enforces beyond each field’s own type. vulnetix config validate and the engine’s plan report a document that breaks one.

On Rule
spec.scope At least one of rule, target or path is set.

CEL variables

spec.when is a CEL expression in the finding context, returning bool. It is evaluated by the suppression engine, over the findings a rule’s anchors have already matched. Fails open. A finding the expression errors on is not suppressed. See where each expression is evaluated. The functions, limits and error codes are on CEL rule expressions.

Variable Type Bound Description
id string 256 chars The advisory identifier, such as CVE-2024-3094 or a GHSA ID.
aliases list(string) 64 items of 256 chars Other identifiers the advisory is known by.
severity string 64 chars Lower case: critical, high, medium, low, or empty when unknown.
cvss double CVSS base score, 0 to 10. 0 when unscored.
epss double EPSS probability, 0 to 1.
epssPercentile double EPSS percentile, 0 to 1.
kev bool Listed in any known-exploited catalogue: CISA KEV, VulnCheck KEV or EU KEV.
exploitMaturity string 64 chars The highest exploit tier, as the CLI --exploits gate grades it: poc, active, weaponized, or empty when none is known.
exploitCount int Number of public exploits known.
reachability string 64 chars Lower case reachability verdict: direct, transitive, semantic, unreachable, or empty when not assessed.
reachable bool Derived. True when reachability is direct, transitive or semantic, the same set the findings page counts as reachable.
internetExposed bool The package is observed on internet-facing infrastructure.
eol bool The package version is end of life.
malicious bool The package is known malware.
fixAvailability string 64 chars available, partial, no_fix, or empty when unknown.
direct bool The package is a direct dependency, not a transitive one.
purl string 2048 chars Package URL of the affected package, with version.
ecosystem string 64 chars Package ecosystem, such as npm, pypi, golang, maven.
cwe list(string) 64 items of 64 chars CWE identifiers, upper case with prefix: CWE-79.
repo string 512 chars Repository full name, owner/name.
branch string 512 chars Branch the finding was scanned on.
path string 1024 chars File the finding came from, such as the manifest or lock file, relative to the repository root.
labels map(string, string) 50 keys, keys and values of 256 chars The key/value labels of the repository the finding is in, as set on the repository’s asset record or in a RepositorySettings document: labels['tier'] == 'prod'. Empty when the repository has none, and in a runtime that does not know the repository’s asset record, so 'tier' in labels is false there.
owner string 512 chars Who owns the repository: a team name, a user name or an email address, as set on its asset record. Empty when none is set.
criticality string 64 chars How much the business depends on the repository: low, medium, high or critical. Empty when none is set, so criticality in ['high', 'critical'] is false for an unclassified repository.
now timestamp The time of evaluation. Callers may fix it; otherwise it is the clock when Eval runs.

Applying this kind

  • Command. vulnetix config apply -f <file>; the CLI line above says from which release. Plan first with vulnetix config plan: it shows each object as create, update, delete or no change, with a planHash that apply then holds to. Apply writes in one transaction.
  • Manager. Each object records the manager that applied it (terraform, console or gitops:<repo>). --prune deletes only objects its own manager owns. See The manager and the config engine.
  • Status. Applied, Unchanged or Deleted, with no other status fields. The phases the engine reports are explained under status phases.

How apply treats it

  • The justification (the OpenVEX vocabulary), the expiry and when (stored as expr) are stored on the suppression.
  • A rule owned by a VEX document or by a VexSource cannot be changed or deleted through the engine.
  • when is evaluated by the suppression engine, after the rule’s anchors have matched; see where each when runs.

Terraform and OpenTofu

The resource is vulnetix_suppression in the vulnetix/resolve provider. Its arguments are the spec in snake case, beside name, labels and annotations from metadata. The Minimal and Advanced HCL are above. The provider’s own reference is vulnetix_suppression.

Import an object that already exists by its name:

# Import an existing Suppression by its name (metadata.name).
terraform import vulnetix_suppression.lodash_prototype_pollution lodash-prototype-pollution

Install, authentication and how state is read: Terraform and OpenTofu.

More examples

examples/Suppression/false-positive.yaml from Vulnetix/config-schemas:

# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/Suppression.schema.json
apiVersion: vulnetix.com/v1
kind: Suppression
metadata:
  name: lodash-cve-2021-23337
spec:
  type: false_positive
  reason: template() is never called with user input in this service.
  justification: vulnerable_code_not_in_execute_path
  scope:
    category: sca
    rule: CVE-2021-23337
    purl: pkg:npm/lodash
    repository: acme/payments-api
  expires: 2027-06-30
  when: '!internetExposed'

examples/Suppression/sast-path.yaml from Vulnetix/config-schemas:

# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/Suppression.schema.json
apiVersion: vulnetix.com/v1
kind: Suppression
metadata:
  name: test-fixtures-secrets
spec:
  type: risk_accepted
  reason: Fixture keys in test data are fake.
  scope:
    category: secrets
    path: testdata/fixtures/keys.pem
    repository: acme/payments-api
    branch: main

Check a file with vulnetix config validate -f <file>. See Validate documents. In an editor, start the file with the schema comment.

Edit this pageSources: config-schemas/schemas/Suppression.schema.json, config-schemas/schemas/common.schema.json, config-schemas/examples/Suppression/minimal.yaml, config-schemas/examples/Suppression/advanced.yaml, config-schemas/examples/Suppression/false-positive.yaml, config-schemas/examples/Suppression/sast-path.yaml, config-schemas/cel/variables.go, terraform-provider-resolve/examples/resources/vulnetix_suppression/minimal.tf, terraform-provider-resolve/examples/resources/vulnetix_suppression/advanced.tf, vdb-site/docs/platform-iac-engine.md, vdb-site/api/internal/handler/config_engine_kinds.go, vdb-site/api/internal/config/suppression.go, vdb-site/api/internal/handler/risk_cel.go
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.