Safeguard
Open Source Security

How Snyk's .snyk file structures ignore rules with expiry...

How Snyk's .snyk file encodes vulnerability ignore rules using reason and expiry date fields, and what happens in CI once an exception lapses.

Priya Mehta
DevSecOps Engineer
7 min read

Every Snyk CLI user eventually runs into the same file: a small YAML document named .snyk sitting quietly at the root of a scanned repository. It looks harmless, but it controls exactly which vulnerabilities Snyk reports on and which ones it silently skips. A single entry can suppress a critical CVE across every future snyk test run, and if that entry never expires, the suppression can outlive the person who wrote it, the ticket that justified it, and the context that made it reasonable in the first place. Understanding the literal structure of this file -- the ignore key, the path wildcards, the reason and expires fields -- is the difference between an ignore rule that functions as a temporary, auditable exception and one that quietly becomes permanent technical debt. This post walks through how Snyk actually builds and enforces that structure, based on its publicly documented CLI behavior.

What does a .snyk file actually look like on disk?

A .snyk file is a plain YAML document, usually created the first time someone runs snyk ignore or snyk wizard against a project, and it lives in version control alongside the code it governs. A minimal example looks like this:

version: v1.25.0
ignore:
  SNYK-JS-LODASH-567746:
    - '*':
        reason: 'No fix available upstream; risk accepted by AppSec'
        expires: 2026-09-30T00:00:00.000Z
        created: 2026-07-07T09:12:04.000Z
patches: {}

The version field pins the schema the file was generated against, so the CLI knows how to parse older files as the format evolves. ignore is a map keyed by Snyk vulnerability ID (here SNYK-JS-LODASH-567746), and patches is a legacy block Snyk still writes out for projects that once used its now-deprecated patch-based remediation. When snyk test runs, it loads this file from the project root, cross-references every finding's ID against the ignore map, and removes matching entries from the CLI output and exit-code calculation before results are ever printed.

How does Snyk structure an individual ignore rule?

Each ignore rule is nested under its vulnerability ID as a list of path-scoped entries, because Snyk lets a single CVE be ignored differently depending on where it appears in the dependency tree. The * wildcard, shown above, means "ignore this vulnerability regardless of which dependency path introduces it" -- the broadest possible scope. A narrower rule can instead target a specific chain, such as express > body-parser > qs, so the same vulnerability ID can be actively flagged in one part of the tree and suppressed in another. Underneath the path key, three fields do the actual work: reason is a free-text string intended to capture the business or technical justification, expires is an ISO 8601 timestamp after which Snyk stops honoring the rule, and created is a timestamp the CLI stamps automatically when the rule is written, giving reviewers a record of how long an exception has actually been in force.

Why do ignore rules carry expiry dates instead of lasting forever?

They carry expiry dates because Snyk's model treats an ignore as a temporary risk-acceptance decision, not a permanent classification change. The expires field is a hard timestamp -- not a duration like "30 days" -- so it doesn't drift relative to when the rule was created; a rule set with expires: 2026-09-30T00:00:00.000Z lapses on that exact date regardless of whether it was written in January or June. Once the current time passes that timestamp, Snyk stops matching the finding against the ignore entry, and the underlying vulnerability reappears in snyk test output and snyk monitor reports as if no exception had ever existed. This is a deliberate design choice: it forces a suppressed CVE back into visibility on a schedule, rather than trusting that someone will remember to revisit a "reason" string written months or years earlier.

How do teams add ignore rules without hand-editing the YAML?

Most teams add them through the snyk ignore CLI command rather than editing the file directly, which is the path Snyk documents and recommends. The typical invocation looks like:

snyk ignore --id=SNYK-JS-LODASH-567746 \
  --reason="No fix available upstream; risk accepted by AppSec" \
  --expiry=2026-09-30

Running this writes the corresponding block into .snyk automatically, filling in created with the current timestamp and defaulting the path to * unless a more specific path is supplied with --path. Because the CLI generates the YAML rather than requiring engineers to format it by hand, the structure stays consistent across a repo's history -- but it also means the file is only as trustworthy as the process around who is allowed to run that command. Nothing in the file format itself distinguishes an ignore added by a security lead after a formal risk review from one added by an individual contributor trying to get a CI pipeline to go green.

What happens in CI once an ignore rule's expiry date passes?

Once the date passes, the previously suppressed vulnerability counts against the scan again, which typically flips a previously green snyk test step in CI back to a failing one. If a pipeline is configured to fail builds on high-severity findings, an expired ignore for a critical CVE like a SNYK-JS or SNYK-PYTHON advisory can block merges and deploys until someone either remediates the underlying dependency or writes a new ignore rule with a fresh expires date and updated reason. In practice, this is the mechanism's real enforcement point: the expiry doesn't delete anything or send a notification on its own inside the open-source .snyk file workflow -- it relies on the next scan surfacing the finding and a human noticing the build turned red.

Where does the .snyk file's per-repo model fall short at scale?

It falls short once an organization has more than a handful of repositories, because each .snyk file is scoped to a single project and there is no built-in cross-repo view of every active or expired ignore. A security team responsible for 50 or 200 services has to either query each repository's file individually or rely on Snyk's centralized web UI and API-based ignore policies, which Snyk has increasingly pushed teams toward for org-wide consistency. Two engineers in different repositories can independently write different reason text and different expires windows for the exact same upstream CVE, with no shared record forcing alignment. And because the file lives in the repository itself, anyone with merge access can extend, edit, or delete an ignore rule -- including its expiry date -- without necessarily triggering a review from whoever originally accepted the risk.

How Safeguard Helps

The .snyk file mechanism is a sound idea -- risk acceptance should be time-boxed and documented -- but its per-repository, YAML-in-source-control design means the audit trail is only as strong as an organization's discipline about who touches those files and when. Safeguard approaches this from the software supply chain layer above any single scanner's file format: rather than trusting that every repository's ignore rules, expiry dates, and reasons are being tracked and honored consistently, Safeguard gives security teams a unified view of dependency risk, exceptions, and their justifications across an entire portfolio of repositories and package ecosystems. That means a critical vulnerability suppressed in one service isn't invisible to the team responsible for the next one that inherits the same dependency, and a risk-acceptance decision made three months ago doesn't quietly disappear into a YAML file nobody is watching. For organizations building on top of tools like Snyk, that portfolio-wide visibility -- who accepted what risk, when it expires, and whether it actually got revisited -- is what turns a useful CLI feature into a defensible, auditable part of a software supply chain security program.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.