Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore/add match results based on OpenVEX documents #1397

Merged
merged 29 commits into from
Sep 13, 2023

Conversation

puerco
Copy link
Contributor

@puerco puerco commented Jul 20, 2023

This (draft) PR adds the initial support for OpenVEX data support in Grype. It handles document handling, data evaluation, filtering of results and presentation of the results to the user.

This is the first stage in the VEX proposal in #1365.

The PR extends Grype's ignore rules system with new VEX data fields and a second stage where a VEX processor does a second evaluation of the configured ignore rules, it is a second stage because VEX not only ignores rules but may also reconsider previously ignored results (this PR does not do that yet).

This tries to explain how vex is wired into the flow of results, green is the match data, and grey is the processing flow:

flowchart TD
 style Z fill:#696,stroke:#333,stroke-width:2px,color:#fff
 style X fill:#696,stroke:#333,stroke-width:2px,color:#fff
 style W fill:#696,stroke:#333,stroke-width:2px,color:#fff
subgraph SG1["Ignore Rules System"]
 B[["ignore.ApplyIgnoreRules()"]]
 D[[Process rule as usual]]
 E[Skip ignore rule]
 C{Rule has VEX data?}
end
subgraph SG2["New VEX Processor"]
 F[[Process remaining VEX Rules]]
end
    Z[Matches]
    X[Matches + Ignore Set]
    W[Final Matches + Ignore Set]
    Z -..->SG1
    
    
    SG1 -.->X
    X -.->SG2
    SG2 -.->W


    A[Parse Ignore Rules] --> B
    B --> C{Rule has VEX data?}
    C ---->|no| D
    C -->|yes| E
    E ---->F 
    
    
Loading

Sample Runs:

This run scans a known alpine image and suppresses all the vulnerabilities using this OpenVEX document:

go run ./cmd/grype/ alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 \
  --vex ./tmp/openvex-demo2.json
  --show-suppressed
 ✔ Vulnerability DB                [no update available]  
 ✔ Loaded image                                      alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126
 ✔ Parsed image                                             sha256:9ed4aefc74f6792b5a804d1d146fe4b4a2299147b0f50eaf2b08435d7b38c27e
 ✔ Cataloged packages              [16 packages]  
 ✔ Scanned for vulnerabilities     [8 vulnerabilities]  
   ├── 0 critical, 2 high, 2 medium, 0 low, 0 negligible (4 unknown)
   └── 8 fixed
NAME        INSTALLED  FIXED-IN  TYPE  VULNERABILITY  SEVERITY                    
libcrypto3  3.0.8-r3   3.0.8-r4  apk   CVE-2023-1255  Medium (suppressed by VEX)   
libcrypto3  3.0.8-r3   3.0.9-r0  apk   CVE-2023-2650  High (suppressed by VEX)     
libcrypto3  3.0.8-r3   3.0.9-r2  apk   CVE-2023-2975  Unknown (suppressed by VEX)  
libcrypto3  3.0.8-r3   3.0.9-r3  apk   CVE-2023-3446  Unknown (suppressed by VEX)  
libssl3     3.0.8-r3   3.0.8-r4  apk   CVE-2023-1255  Medium (suppressed by VEX)   
libssl3     3.0.8-r3   3.0.9-r0  apk   CVE-2023-2650  High (suppressed by VEX)     
libssl3     3.0.8-r3   3.0.9-r2  apk   CVE-2023-2975  Unknown (suppressed by VEX)  
libssl3     3.0.8-r3   3.0.9-r3  apk   CVE-2023-3446  Unknown (suppressed by VEX)

That document suppresses one vulnerability using not_affected with a status of vulnerable_code_not_present. By applying this configuration file we can configure Grype to only suppress results marked with that status and justification:

grype alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 \
   --vex ./tmp/file-mulit-cve-openvex-json
   --show-suppressed
   --config tmp/file-config-vex-status-justification-yaml
 ✔ Vulnerability DB                [no update available]  
 ✔ Loaded image                                      alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126
 ✔ Parsed image                                             sha256:9ed4aefc74f6792b5a804d1d146fe4b4a2299147b0f50eaf2b08435d7b38c27e
 ✔ Cataloged packages              [16 packages]  
 ✔ Scanned for vulnerabilities     [8 vulnerabilities]  
   ├── 0 critical, 2 high, 2 medium, 0 low, 0 negligible (4 unknown)
   └── 8 fixed
NAME        INSTALLED  FIXED-IN  TYPE  VULNERABILITY  SEVERITY                    
libcrypto3  3.0.8-r3   3.0.8-r4  apk   CVE-2023-1255  Medium                       
libcrypto3  3.0.8-r3   3.0.9-r0  apk   CVE-2023-2650  High                         
libcrypto3  3.0.8-r3   3.0.9-r2  apk   CVE-2023-2975  Unknown                      
libcrypto3  3.0.8-r3   3.0.9-r3  apk   CVE-2023-3446  Unknown (suppressed by VEX)  
libssl3     3.0.8-r3   3.0.8-r4  apk   CVE-2023-1255  Medium                       
libssl3     3.0.8-r3   3.0.9-r0  apk   CVE-2023-2650  High                         
libssl3     3.0.8-r3   3.0.9-r2  apk   CVE-2023-2975  Unknown                      
libssl3     3.0.8-r3   3.0.9-r3  apk   CVE-2023-3446  Unknown (suppressed by VEX)

Flags

In addition to the VEX ignore rules, the CLI has two new flags that control how VEX impacts the results.

--vex=path/to/doc.openvex.json
--vex-filter=true

The first flag --vex passes to Grype the path of one or more VEX documents to be parsed and used when processing the scan results. The second one enables and disables the default VEX ignore rules which are to honor statements with a VEX status of fixed or not_affected. At this time only the filter part is implemented. Recovering matches from ignore sets based on affected status is not yet implemented.

The VEX processor is an interface that has two purposes: Read VEX documents and Apply the VEX data to results. It is designed to be VEX-implementation agnostic, this PR includes the OpenVEX implementation.

About the PR:

  • This PR depends on an upcoming revision to the OpenVEX spec and its go libraries, this revision has not merged yet (ref OPEV-0014 OPEV-0015 openvex/go-vex#45), the go mod has local replacements for development purposes.
  • I consider the logic in this PR to be complete, there are no tests yet but I will add them if the approach looks OK.
  • The VEX processor writes to a debugger file, this will be removed in the final version

Signed-off-by: Adolfo García Veytia (Puerco) puerco@chainguard.dev

@wagoodman
Copy link
Contributor

wagoodman commented Aug 3, 2023

for matches that were added due to an affected status can we capture the original vex statement in the match details? or a way to map a match back to the original vex statement?

@puerco
Copy link
Contributor Author

puerco commented Aug 3, 2023

can we capture the original vex statement in the match details.

Ah great idea, this could be useful for both cases. This change is not considering affected yet but it's also important to keep them for not_affected and fixed.

)

flags.BoolP(
"vex-filter", "", true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could probably drop this flag on the first pass (where if the user passes a vex doc then it implicitly filters)

Copy link
Contributor

@wagoodman wagoodman Aug 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from the conversation: this was here to enable filtering or enable adding matches based on vex. Since the ignore rules already covered in the application configuration we can try to at least cover the addition of matches based on vex statements:

GRYPE_VEX_ADD=affected,under_investigation     # default "", or allow "true" which means just "affected"

So by default grype would filter by default when provided a vex document, but the user would need to opt-into augmenting/adding matches based on vex documents.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(consider this config example to be not finalized / illustrative)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, we now have the results augmentation feature implemented see my comment below.

@wagoodman
Copy link
Contributor

from an offline conversation:

  • case: grype finds a match and we find an "affected" vex entry, we should add a new match details entry to the match in question

@puerco puerco force-pushed the openvex branch 2 times, most recently from 4caa03e to 46354a5 Compare August 5, 2023 23:34
@puerco puerco force-pushed the openvex branch 3 times, most recently from 8e3aeaf to e1abdfe Compare August 18, 2023 15:58
@puerco
Copy link
Contributor Author

puerco commented Aug 18, 2023

@wagoodman @kzantow @willmurphyscode we finally merged the required functionality into the @openvex libraries! This should be ready to run by itself 🎉

Can you enable the CI to run to finish it?

@kzantow
Copy link
Contributor

kzantow commented Aug 19, 2023

@puerco I think the replace directive will need to be removed before CI runs properly/

@puerco
Copy link
Contributor Author

puerco commented Aug 19, 2023

Duh, I rebased and forgot to remove it. The replace is gone but now it is stuck again waiting for approval again, I guess this is because it is my first contribution to the repo :/

@puerco
Copy link
Contributor Author

puerco commented Aug 22, 2023

I rebased this PR to the latest release of the OpenVEX libraries. I also fixed a bunch of typos on #1455 to have a previous contribution so that GitHub runs the CI automatically and I don't have to nag you all :)

@puerco puerco changed the title OpenVEX Support (initial draft) OpenVEX Support Aug 23, 2023
@puerco
Copy link
Contributor Author

puerco commented Aug 23, 2023

OK, we now have support for affected and under_investigation statements. As discussed offline, by default grype will not augment results from vex data unless the user opts-in by defining GRYPE_VEX_ADD=[affected][,under_investigation].

This env var is wired to a vex-add setting which can also be defined in the config file, it is not exposed via CLI flags.

When enabled, the current implementation will move any matches that are ignored back to the active result sets when a statement with those vex statuses applies to it.

When moved back to the results, the vex processor will add a record with a new openvex matcher and record the parameters used to match and the statement that caused the result to be considered again. Here is a sample from the json output:

    {
     "type": "exact-direct-match",
     "matcher": "openvex-matcher",
     "searchedBy": {
      "Vulnerability": "CVE-2023-1255",
      "Product": "pkg:oci/alpine@sha256%3A124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126",
      "Subcomponents": [
       "pkg:apk/alpine/libcrypto3@3.0.8-r3?arch=x86_64&upstream=openssl&distro=alpine-3.17.3"
      ]
     },
     "found": {
      "Statement": {
       "vulnerability": {
        "name": "CVE-2023-1255"
       },
       "timestamp": "2023-07-17T18:28:47.696004345-06:00",
       "products": [
        {
         "@id": "pkg:oci/alpine@sha256%3A124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126",
         "subcomponents": [
          {
           "@id": "pkg:apk/alpine/libssl3@3.0.8-r3"
          },
          {
           "@id": "pkg:apk/alpine/libcrypto3@3.0.8-r3"
          }
         ]
        }
       ],
       "status": "affected"
      }
     }
    }

I've added an example openvex document with an affected statement (affect-CVE-2014-54321.openvex.json) to the example files commit (titled DROPME... currently at 4a76441 ). The vex document can be used together with ignore-CVE-2023-1255.yaml to test the results augmentation feature.

Example invocation:

GRYPE_VEX_ADD=affected grype \ 
         alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 \
         -c tmp/ignore-CVE-2023-1255.yaml \
         --show-suppressed
         --vex tmp/affect-CVE-2014-54321.openvex.json

@wagoodman @kzantow PTAL and let me know what you think.

@puerco
Copy link
Contributor Author

puerco commented Aug 31, 2023

@wagoodman I've wired the OpenVEX matcher to the test framework and tests for it now run in addition to the regular matchers. The new test loop can ingest any number of vex documents preparing it for other possible vex processors different from OpenVEX.

🟢 Tests are green now, please take a look when you have a chance. Once we're ready I'll drop the commit with the example files (currently at 062ff1f )

Do you want to take a look at how suppressed matches are surfaced in the UI as we discussed offline?

puerco and others added 17 commits September 12, 2023 12:57
This commit modifies the identifier synthesizer function to parse references
using GGCR. It also adds a simple test.

Signed-off-by: Adolfo García Veytia (Puerco) <puerco@chainguard.dev>
This commit bumps the maximum function length to 73 to accomodate
the new flag in AddFlags()

Signed-off-by: Adolfo Garcia Veytia (puerco) <puerco@chainguard.dev>
This commit adds a new test and fixtures to test the VEX matchers
along the rest of the matchers in TestMatchByImage(). As the VEX
matchers operate on previously ignored matches a new loop was added
to the test to accomodate the different testing model.

Signed-off-by: Adolfo García Veytia (Puerco) <puerco@chainguard.dev>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Based on Alex's previous caommit

Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
Signed-off-by: Adolfo García Veytia (Puerco) <puerco@chainguard.dev>
Signed-off-by: Adolfo García Veytia (Puerco) <puerco@chainguard.dev>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit adds a VEX section to the main Grype README. It adds
an example document and details on how vex rules can be written.

Signed-off-by: Adolfo García Veytia (Puerco) <puerco@chainguard.dev>
@wagoodman wagoodman changed the title OpenVEX Support Ignore/add match results based on OpenVEX documents Sep 13, 2023
@wagoodman wagoodman added the enhancement New feature or request label Sep 13, 2023
@wagoodman wagoodman merged commit b952d38 into anchore:main Sep 13, 2023
9 checks passed
@kzantow
Copy link
Contributor

kzantow commented Sep 13, 2023

Thanks very much for this contribution, @puerco!

@puerco
Copy link
Contributor Author

puerco commented Sep 13, 2023

Thank you so much for all your patience and help @wagoodman @kzantow !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

3 participants