Skip to main content
A project’s Vulnerabilities page is where you say, for each known vulnerability in the project’s components, whether your product is affected. What you state is what Earnie publishes as VEX (Vulnerability Exploitability eXchange) for the project. The people who receive your SBOM and scan it can then stop flagging what doesn’t apply to your product. To open it, select a project, then Vulnerabilities in the sidebar. It sits after Dependencies. It appears where your organisation has open-source matching or the enrichment module. Every role that can read the project can open it.

What a Row Is

A row is one CVE in one exact component version of the project’s current inventory. That inventory is the latest completed scan of the default branch, its declared dependencies, an imported SBOM, and the resolved dependency graph. Earnie reads the rows fresh each time and doesn’t store them. Each row shows:
  • the CVE, with KEV when it’s on the CISA Known Exploited Vulnerabilities list
  • the component and version
  • the severity and the EPSS score
  • the version that fixes it
  • its status, its justification, and who last updated it
A statement is stored apart from scans, so a new scan never changes it. A statement is also about one version: a statement about version 2.14.1 says nothing about 2.15.0, and a new version starts with nothing stated.

Statuses

Justifications for Not Affected

Finding the Rows You Need

  • Switch status. The segments at the top show how many rows each status holds, for the other filters you’ve set.
  • Filter. Severity keeps the severities you choose, Known exploited keeps the KEV rows, and Search vulnerabilities matches part of a CVE ID, an alias, or a component.
  • Share a view. The address holds your filters, so you can paste a link to a view.
  • Load more. A long list loads fifty rows at a time. Choose Show more for the next page.

Why It’s Here

A row’s panel starts with Why it’s here, so you can decide with the context in front of you. It says which inventory brought the component into the project:
  • Matched in your code
  • Declared dependency
  • From an imported SBOM
  • Resolved dependency
  • Component used by crypto or AI code
A component can have several. When the project’s dependency graph knows the package, the panel says Direct dependency, or lists the chains that pull it in, from a direct dependency down to the package, with the manifest that declares it. It shows the shortest few chains and says when there are more. The panel also links onward:
  • Open in Dependencies opens the package in the graph.
  • Open in Review opens a component your code matched in the Review Workspace.
  • Advisory opens the public advisory in a new tab, with the other IDs the vulnerability is known by.

Recording and Withdrawing Statements

Admins and Operators can record and withdraw statements. A Viewer can read the list and every history, and the page says who can record.
  • Record one statement. Select a row to open its panel. Choose a status, fill in what it asks for, and choose Record statement. The panel closes and the row moves to its new status.
  • Record many at once. Tick several rows and choose Record statement in the bar above the table. One statement goes onto every selected row, all together or none. Changing a filter clears the selection.
  • Withdraw a statement. In a row’s panel, choose Withdraw statement. Or tick rows that all have one and choose Withdraw. Earnie asks first. The row goes back to Not decided and stops being published.
Withdrawing erases nothing. The panel’s History keeps every revision, newest first, with who made it, whether a person or an agent did, and when.
A statement is a fact about the product, not a waiver. It never approves a policy violation. Policy Approvals stay the place for that. See When the gate blocks a merge. A policy only treats a CVE differently when its rule reads the VEX status, as the two built-in vulnerability policies below do.

Statements in Policies

A policy can read a statement through the VEX status field of a vulnerability (vulnerability.vex_status). Its values are not_affected, affected, fixed, under_investigation and undecided. A CVE with no statement, or a withdrawn one, is always undecided, so a rule never has to check that the field is there. Recording or withdrawing a statement re-evaluates the project’s policies. The built-in policies Block known exploited vulnerabilities and Block high-severity vulnerabilities skip a CVE whose statement is in their Ignored VEX statuses parameter, which is Not affected and Fixed by default. If a fixed CVE should keep blocking until the component is upgraded, remove Fixed from that parameter. A policy you write sees every CVE until you add a clause such as !(v.vex_status in ["not_affected", "fixed"]).

Statements in Counts

A project’s CVE counts (the project summary, the High CVEs column of the projects list, and what a coding agent reads) leave out a CVE the project has stated Not affected or Fixed on every version of the component that carries it. A CVE still open on any version counts. The dashboard’s CVE cards are recorded at each scan, so they show a new statement from the project’s next scan. The Vulnerabilities page always lists every CVE, stated or not.

Statements in Exports

A CycloneDX export carries each CVE’s statement as of the moment the export was made, in the vulnerability’s analysis: Not affected, Affected (exploitable), Fixed (resolved) or Under investigation (in triage), with the justification and your statement text. A CVE with no statement carries none. SPDX exports do not carry statements. To give a scanner your statements, export VEX (CycloneDX) with the SBOM. The VEX file lists only the CVEs you have a statement for, and points at the components of the SBOM exported with it, so a scanner such as Trivy can read both (trivy sbom sbom.cdx.json --vex vex.cdx.json) and stop reporting what you stated not affected or fixed. The CRA compliance package includes the VEX file too. If your scanner reads OpenVEX instead, export VEX (OpenVEX): the same statements, with each product named by its package URL, so it needs no SBOM beside it.

Statements in CRA Reporting

Where CRA reporting is switched on for your deployment, the statement for a component and CVE appears next to the decision you make about an exposure. It is context only: Earnie never confirms, dismisses, or closes anything because of a statement. Deciding about an exposure. The To decide view of CRA reporting lists every known exploited vulnerability that nobody has decided about yet. Each row shows the CVE, the component and version, the project, when CISA listed it (KEV), whether it’s known in ransomware, and the project’s vulnerability statement in words, such as Not affected, not in the execute path, or No statement. Members who can decide on CRA cases (the Admin role) see two buttons on each row: Anyone else sees one line that says who decides, and no button. The suggested dismissal. When the project’s statement for that component and CVE is Not affected, the dismiss form opens with the matching reason and the statement’s impact statement as the note, under the line Prefilled from the vulnerability statement. It’s a suggestion. Change either field, and choose Dismiss exposure yourself. Earnie never dismisses on a statement alone. Choosing the button twice, or retrying after a failure, records the decision once. If someone decided about the exposure in the meantime, the form says so and records nothing. On a case. A case page shows the component’s Vulnerability statement for that project, with a link to open it on the Vulnerabilities page, or No statement recorded. Members who can decide on CRA cases can Close case or Reopen case at the top of the page. Close case asks for a reason, No longer reportable or Withdrawn, and takes an optional note. Reopen case asks for a note (required) and opens the case again on its original deadlines.

From a Coding Agent or the Command Line

Coding agents usually record statements from where the code is. They use MCP or the earnie vulnerabilities command, with an API key that holds the vulnerabilities:decide permission. The page then shows those statements as made by an agent.

Who Can Do What

An API key can hold vulnerabilities:decide, and reading vulnerabilities needs findings:read. See API keys.

What’s Next

Triage the findings a scan raised, or see how each package reached your project.