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

fix(dotnet): don't include non-runtime libraries into report for *.deps.json files #7039

Conversation

DmitriyLewen
Copy link
Contributor

@DmitriyLewen DmitriyLewen commented Jun 27, 2024

Description

Dependencies with empty runtime, runtimeTarget and native fields in target section are not needed by the runtime, and the dotnet build command doesn't create *.dll files for them.
(see #4282 (comment)).
Don't include these libraries into report.

Related Issues

Related Discussions

Checklist

  • I've read the guidelines for contributing to this repository.
  • I've followed the conventions in the PR title.
  • I've added tests that prove my fix is effective or that my feature works.
  • I've updated the documentation with the relevant information (if needed).
  • I've added usage information (if the PR introduces new options)
  • I've included a "before" and "after" example to the description (if the PR is a user interface change).

@DmitriyLewen DmitriyLewen self-assigned this Jun 27, 2024
@DmitriyLewen DmitriyLewen marked this pull request as ready for review June 27, 2024 12:05
@DmitriyLewen DmitriyLewen requested a review from knqyf263 as a code owner June 27, 2024 12:05
Comment on lines 90 to 91
// We're still not sure that we need to skip libraries built into .NETCore (or that we detect them correctly).
// So we mark these libraries as Dev to skip the scan by default, but keep the options for displaying these libraries.
Copy link

@ericstj ericstj Jun 27, 2024

Choose a reason for hiding this comment

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

Packages which don't contribute runtime assets to the application cannot contribute to a runtime vulnerability since nothing from the package persists at runtime. Runtime assets can be identified by examining the targets section since that's what the host uses to probe for those.

There are lots of ways packages might be referenced by an app and excluded from runtime.

The package might be referenced with ExcludeAssets="Runtime", the package might have been superseded by the .NET runtime itself and excluded but the build, or the package might have overlapping assets with another package that is preferred. In all cases - if it's bits don't make it to the final app it cannot be a source of a vulnerability in that app.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

in general I think the same way.
thank you for detailing this 👍

In all cases - if it's bits don't make it to the final app it cannot be a source of a vulnerability in that app.

There are times when users want to see dependencies that are not used at runtime (we encountered this in nodejs).
That's why we've added options to allow users to see all dependencies (we hide them by default). for example, this may be needed not for scanning vulnerabilities, but for generating a SBOM

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The package might be referenced with ExcludeAssets="Runtime"

Do we need to check this case?
Can you write more info about this?

docs don't have info about ExcludeAssets field.

Copy link
Collaborator

Choose a reason for hiding this comment

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

in general I think the same way.

thank you for detailing this 👍

In all cases - if it's bits don't make it to the final app it cannot be a source of a vulnerability in that app.

There are times when users want to see dependencies that are not used at runtime (we encountered this in nodejs).

That's why we've added options to allow users to see all dependencies (we hide them by default). for example, this may be needed not for scanning vulnerabilities, but for generating a SBOM

I would add more contexts. As interest in supply chain security grows, there is a demand to understand vulnerabilities in packages that are used for CI/CD and other purposes, even if they are not included in production applications and are used only for development.

If the library is not used at all, even for development purposes, there is no need to include it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@ericstj Since we're unfamiliar with .NET Core, we need your input. Given the above context, do you think we don't have to save these libraries?

Copy link
Collaborator

@knqyf263 knqyf263 Jul 9, 2024

Choose a reason for hiding this comment

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

@ericstj In other ecosystems, it is common to include test assertion libraries as development libraries. And while these libraries are not used at runtime, their vulnerability is important.

For instance - a build target that inserts code into the binary. That package might appear without any runtime assets, however such a package is not the norm. .

This example you gave is certainly not legitimate, but are libraries used for development purposes in general use such as the one I gave not included in deps.json?

Copy link

@ericstj ericstj Jul 11, 2024

Choose a reason for hiding this comment

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

deps.json isn't the file to see all dependencies that might be used at development time. It's used for loading binaries at runtime.

At development time projects use PackageReference (direct references) in the project, which gets computed to the full package graph in project.assets.json. The old format packages.config had a flattened graph in the single file and was really just a log for the package modifications that were made to the project file separately. These two files are better for identifying development dependencies - and are used by component governance for that purpose. They are present on the build machine / source control. There's also the new SBOM infrastructure which is better suited as a catch all.

This example you gave is certainly not legitimate, but are libraries used for development purposes in general use such as the one I gave not included in deps.json?

They may or may not be included, it depends on the type of package and how its referenced. deps.json is only used for telling the runtime what to load. When a library is present you can be certain it's used - so if that library/package is vulnerable it should be flagged. If the package is listed in the deps file, you can be certain it was at least referenced - but it may have been eliminated by the build and not loadable at runtime - so it should not be flagged. You can't assume that a package being absent means it wasn't used at dev time since the deps.json doesn't list all development time dependencies.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hm.. It looks like that we can remove non-runtime dependencies.
Also we need to write in docs that Trivy only detects runtime deps from *.deps.json

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for your explanation. It might be similar to Go binary scanning. It doesn't have any development modules, while go.mod includes it.

@DmitriyLewen We can just delete non-runtime dependencies and improve it later if we see any feedback.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done 👍
@knqyf263 @ericstj can you review this PR?

@knqyf263
Copy link
Collaborator

knqyf263 commented Jul 2, 2024

@DmitriyLewen Can you create an issue so we can add it to the v0.54.0 milestone?

@DmitriyLewen
Copy link
Contributor Author

@knqyf263 Created #7079

@DmitriyLewen DmitriyLewen force-pushed the fix-dotnet-core/add-dev-flag-for-libs-built-into-netcore branch from 910d497 to 21c6cd3 Compare July 15, 2024 02:35
@DmitriyLewen DmitriyLewen changed the title fix(dotnet): mark libraries built into .NETCore as Dev fix(dotnet): don't include non-runtime libraries for *.deps.json files Jul 15, 2024
@DmitriyLewen DmitriyLewen changed the title fix(dotnet): don't include non-runtime libraries for *.deps.json files fix(dotnet): don't include non-runtime libraries into report for *.deps.json files Jul 15, 2024
Copy link

@ericstj ericstj left a comment

Choose a reason for hiding this comment

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

The behavior looks correct, just some suggestions to change the comments to match and add a test.

})
return true
}
// Check that `runtime`, `runtimeTarget` and `native` sections are empty
Copy link

Choose a reason for hiding this comment

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

Looks to me like it checks if they are not empty.

Suggested change
// Check that `runtime`, `runtimeTarget` and `native` sections are empty
// Check that `runtime`, `runtimeTarget` and `native` sections are not empty

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed in afe12b4

Type string `json:"type"`
StartLine int
EndLine int
// isRuntimeLibrary returns true if library doesn't contain `runtime`, `runtimeTarget` and `native` sections.
Copy link

Choose a reason for hiding this comment

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

Suggested change
// isRuntimeLibrary returns true if library doesn't contain `runtime`, `runtimeTarget` and `native` sections.
// isRuntimeLibrary returns true if library contains `runtime`, `runtimeTarget` or `native` sections, or if the library is missing from `targetLibs`.

I think this function returns true if the library contains one of these sections, or if the library is completely missing from the section. The behavior looks correct, just the comment seems inverted.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I updated this function, but forgot to update comment.
Thanks!
Fixed in afe12b4

@@ -0,0 +1,96 @@
{
Copy link

Choose a reason for hiding this comment

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

Would it be possible to add another testcase that references some of the commonly reported false positives and proves that those aren't flagged? For example - a deps file listing a vulnerable version of System.Net.Http etc. Here's a sample deps file:
testRuntimeDeps.deps.json

This was created with

dotnet new console -f net6.0
dotnet add package NETStandard.Library --version 1.6.0
dotnet build

This shows that all the old packages (some vulnerable) making up the NETStandard surface area are all excluded when targeting the latest frameworks which provide inbox support for all those package.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Your test file is too large.
So I only inserted System.Net.Http and NETStandard.Library libraries into test file. - ca87c12

@DmitriyLewen
Copy link
Contributor Author

I updated PR according to notes
@knqyf263 @ericstj if you don't have any suggestions - i think we can merge this PR.

@knqyf263 knqyf263 added this pull request to the merge queue Jul 19, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to no response for status checks Jul 19, 2024
@knqyf263 knqyf263 added this pull request to the merge queue Jul 19, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to no response for status checks Jul 19, 2024
@knqyf263 knqyf263 added this pull request to the merge queue Jul 22, 2024
Merged via the queue into aquasecurity:main with commit 5bc662b Jul 22, 2024
17 checks passed
skahn007gl pushed a commit to skahn007gl/trivy that referenced this pull request Jul 23, 2024
@ericstj
Copy link

ericstj commented Aug 27, 2024

@DmitriyLewen It looks like this might not be working correctly. We're still seeing reports of this when using the latest trivvy 0.54.1. Is there a way to get some diagnostic information out of trivvy to see why it's still flagging vulnerabilities here?

@DmitriyLewen DmitriyLewen deleted the fix-dotnet-core/add-dev-flag-for-libs-built-into-netcore branch August 28, 2024 01:44
@DmitriyLewen
Copy link
Contributor Author

Hello @ericstj
Trivy has debug flag, but I'm not sure if it will help you.
It seems like one way is to use the IDE debugger to step through it.
Or you can send me a test file and I'll check it.

@ericstj
Copy link

ericstj commented Aug 28, 2024

@DmitriyLewen
The command I was trying was this:
docker run -it aquasec/trivy:0.54.1 image mcr.microsoft.com/dotnet/sdk:8.0 --scanners vuln --vuln-type library --debug

It reports a vulnerability in System.Formats.Asn1, however all files present are updated.

I believe it's still seeing mention to the older package versions in deps files, however I believe all those deps files should have empty targets sections. If I search the container for any other copies of this file, I do see one in powershell, but that's also of sufficient version to not trigger.

@DmitriyLewen
Copy link
Contributor Author

Hello @ericstj
I found file with System.Formats.Asn1dependency
Trivy found this file from spdx file:

➜  7039 docker run -it --rm mcr.microsoft.com/dotnet/sdk:8.0 cat /usr/share/powershell/.store/powershell.linux.arm64/7.4.4/powershell.linux.arm64/7.4.4/tools/net8.0/any/Modules/PSReadLine/_manifest/spdx_2.2/manifest.spdx.json | grep '"name": "System.Formats.Asn1"' -A 16
      "name": "System.Formats.Asn1",
      "SPDXID": "SPDXRef-Package-D60BE9A079A339572CC368D77C4FE3CD4860E5B2846B9831B99485A3ABD77F4B",
      "downloadLocation": "NOASSERTION",
      "filesAnalyzed": false,
      "licenseConcluded": "NOASSERTION",
      "licenseDeclared": "NOASSERTION",
      "copyrightText": "NOASSERTION",
      "versionInfo": "6.0.0",
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE-MANAGER",
          "referenceType": "purl",
          "referenceLocator": "pkg:nuget/[email protected]"
        }
      ],
      "supplier": "NOASSERTION"
    },

@ericstj
Copy link

ericstj commented Aug 29, 2024

Oh, that's interesting. It's an SBOM from powershell. It's another false positive since they aren't actually shipping that binary. I'll follow up with them to see if it's a problem they can fix.

Thank you for your help. Is there any trick to getting the map of components out of the scanner or more logging out of the scanner?

@DmitriyLewen
Copy link
Contributor Author

Is there any trick to getting the map of components out of the scanner

json format + '--list-all-pkgs flag shows all detected packages.

@ericstj
Copy link

ericstj commented Aug 30, 2024

Perfect, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat(.NET): mark some deps from .deps.json files as Dev
3 participants