Skip to content

feat: add Bottlerocket OS package analyzer #8653

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

Merged
merged 1 commit into from
May 23, 2025

Conversation

0intro
Copy link
Contributor

@0intro 0intro commented Mar 31, 2025

Description

This change adds the Bottlerocket OS package analyzer.

This analyzer parses the package information provided in the application-inventory.json file, as specified on:

https://bottlerocket.dev/en/os/1.37.x/concepts/variants/#software-inventory

This change also defines the Bottlerocket OS family.

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
Copy link
Contributor

Hi @0intro
Thank you for your work.

Trivy repository has been growing bigger and bigger lately.
So it's getting harder to maintain.
So we're trying to add only the functionality that the community needs.

Can you create a new Discussion with a proposal to add Bottlerocket?
If this future is in demand by the community - we'll review/merge etc. this PR.

@0intro
Copy link
Contributor Author

0intro commented Apr 1, 2025

Thanks. I've opened #8661.

Copy link
Collaborator

@knqyf263 knqyf263 left a comment

Choose a reason for hiding this comment

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

Thanks for your great contribution! Since I have already heard about some needs on Bottlerocket, I think we want to move forward with this PR.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we shrink the test data? Our policy for unit tests is not to include data that doesn't change the code path, so I think it's fine to keep it simple with just 2–3 cases, including the normal case and edge cases (if any).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, I've shrunk the test data down.

@knqyf263 knqyf263 requested a review from Copilot April 7, 2025 08:15
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Comments suppressed due to low confidence (1)

pkg/fanal/analyzer/pkg/bottlerocket/bottlerocket.go:72

  • Consider wrapping the JSON unmarshal error with additional context to improve debugging clarity, such as including the source file or input length.
err = json.Unmarshal(b, &applicationInventory)

@0intro 0intro force-pushed the djc/analyzer-bottlerocket branch from f84d18a to 3dfed29 Compare April 7, 2025 09:45
@0intro 0intro requested a review from knqyf263 April 9, 2025 07:29
@knqyf263
Copy link
Collaborator

knqyf263 commented Apr 9, 2025

Can you please take a look at the test failure?

@0intro 0intro force-pushed the djc/analyzer-bottlerocket branch from 3dfed29 to 959aa16 Compare April 9, 2025 09:07
@0intro
Copy link
Contributor Author

0intro commented Apr 9, 2025

I've just fixed the linter issue.

@knqyf263
Copy link
Collaborator

knqyf263 commented Apr 9, 2025

You can run mage lint:fix and mage test:unit locally.

@0intro 0intro force-pushed the djc/analyzer-bottlerocket branch from 959aa16 to e4808c8 Compare April 9, 2025 13:17
@0intro
Copy link
Contributor Author

0intro commented Apr 9, 2025

Surprisingly, the first pass of mage lint:fix lead to a build error. It should be fixed now.

Copy link
Collaborator

@knqyf263 knqyf263 left a comment

Choose a reason for hiding this comment

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

It looks great! I left small comments.

Comment on lines 66 to 69
b, err := io.ReadAll(r)
if err != nil {
return nil, err
}

var applicationInventory ApplicationInventory
err = json.Unmarshal(b, &applicationInventory)
if err != nil {
return nil, err
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there any reason all the file content needs to be loaded?

Suggested change
b, err := io.ReadAll(r)
if err != nil {
return nil, err
}
var applicationInventory ApplicationInventory
err = json.Unmarshal(b, &applicationInventory)
if err != nil {
return nil, err
}
var applicationInventory ApplicationInventory
if err := json.NewDecoder(r).Decode(&applicationInventory); err != nil {
return nil, err
}

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.

}

func (a bottlerocketPkgAnalyzer) Type() analyzer.Type {
return analyzer.TypeBottlerocket
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: Other package analyzers use the name of the package manager, like rpm and apk. Since Bottlerocket is also an OS name, I would rename it to bottlerocket-package, bottlerocket-pkg or things like that so it will not get confused with Bottlerocket OS analyzer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a good point, but I haven't been able to find a good name. What do you think about bottlerocket-inventory? The file is usually called either application inventory or software inventory in the Bottlerocket documentation.

Copy link
Collaborator

Choose a reason for hiding this comment

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

bottlerocket-inventory sounds good to me.

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.

@0intro 0intro force-pushed the djc/analyzer-bottlerocket branch from e4808c8 to eeb2241 Compare April 11, 2025 19:38
@0intro 0intro requested a review from knqyf263 April 11, 2025 19:40
@0intro 0intro force-pushed the djc/analyzer-bottlerocket branch from eeb2241 to 16218d2 Compare April 14, 2025 12:16
@0intro
Copy link
Contributor Author

0intro commented Apr 14, 2025

I've renamed the bottlerocket package to bottlerocket_inventory.

Copy link
Collaborator

@knqyf263 knqyf263 left a comment

Choose a reason for hiding this comment

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

LGTM.
@DmitriyLewen Can you also take a look?

Copy link
Contributor

@DmitriyLewen DmitriyLewen left a comment

Choose a reason for hiding this comment

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

I see a few things:

  1. I think Trivy shows warning (something like WARN Unsupported os family="bottlerocket"). This might confuse users. Let's create a new ospkg driver. This driver will only show the Info log that Trivy does not support vulnerability detection for bottlerocket packages (the Detect function will simply return nil).
    @knqyf263 wdyt?
  2. I think we need to update the purl package.
    We can add the bottlerocket purl type to Trivy (until package-url/purl-spec#454 is merged). You also need to update other functions (purlType, LangType, etc.)
    or we can use generic type
  3. Add Bottlerocket page in docs

Copy link
Contributor

Choose a reason for hiding this comment

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

let's use same name as in package (bottlerocket_inventory.go) (with _)

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.

Copy link
Collaborator

Choose a reason for hiding this comment

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

If I'm not mistaken, it's still mixed.

pkg/fanal/analyzer/pkg/bottlerocket_inventory/bottlerocket-inventory_test.go should be pkg/fanal/analyzer/pkg/bottlerocket-inventory/bottlerocket-inventory_test.go

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, it should be fine now.

@knqyf263
Copy link
Collaborator

I think Trivy shows warning (something like WARN Unsupported os family="bottlerocket"). This might confuse users. Let's create a new ospkg driver. This driver will only show the Info log that Trivy does not support vulnerability detection for bottlerocket packages (the Detect function will simply return nil).

I thought we could document Trivy supports Bottlerocket only for SBOM, but UX would be better if we show the log message like you suggested.

@DmitriyLewen
Copy link
Contributor

Thanks for pointing this out, I forgot to write about it in the review:
We need to add information to the bottlerocket OS documentation.

@0intro 0intro force-pushed the djc/analyzer-bottlerocket branch from 16218d2 to e6cfae8 Compare April 15, 2025 09:02
@knqyf263 knqyf263 requested a review from DmitriyLewen April 16, 2025 05:41
@DmitriyLewen
Copy link
Contributor

@0intro do you have time to update this PR as per notes from #8653 (review)?

@0intro
Copy link
Contributor Author

0intro commented Apr 16, 2025

@0intro do you have time to update this PR as per notes from #8653 (review)?

Yes, I'll take a look.

@0intro 0intro force-pushed the djc/analyzer-bottlerocket branch from e6cfae8 to 11e5765 Compare April 16, 2025 15:07
@0intro
Copy link
Contributor Author

0intro commented Apr 16, 2025

I've added a stub bottlerocket ospkg driver, which should get rid of the Unsupported os family="bottlerocket" warning.

@0intro 0intro requested a review from knqyf263 April 18, 2025 17:28
@0intro 0intro force-pushed the djc/analyzer-bottlerocket branch 2 times, most recently from 83f5a11 to 5cc52ee Compare April 23, 2025 09:26
@knqyf263
Copy link
Collaborator

I picked up some images from https://gallery.ecr.aws/bottlerocket/, but their OS was Amazon Linux. How can I test this PR with actual images?

@0intro
Copy link
Contributor Author

0intro commented Apr 28, 2025

To deploy Bottlerocket on AWS, I've created an EC2 instance using resolve:ssm:/aws/service/bottlerocket/aws-ecs-2/x86_64/latest/image_id as an ImageId.

Copy link
Collaborator

@knqyf263 knqyf263 left a comment

Choose a reason for hiding this comment

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

I had trouble enabling SSM properly when launching a Bottlerocket AMI on EC2, so I wasn’t able to access the shell. I was finally able to view Bottlerocket’s root filesystem by launching it as an instance within an EKS cluster. If there’s an easier way to do this, I’d really appreciate it if you could let me know—it would make future testing much smoother.

Sorry for the delay in commenting; it took some time to get the setup working correctly.

Comment on lines +23 to +24
"aarch64-bottlerocket-linux-gnu/sys-root/usr/lib/os-release",
"x86_64-bottlerocket-linux-gnu/sys-root/usr/lib/os-release",
Copy link
Collaborator

@knqyf263 knqyf263 May 1, 2025

Choose a reason for hiding this comment

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

Have you ever seen a case where /usr/lib/os-release doesn't exist and only ${arch}-bottlerocket-linux-gnu/sys-root/usr/lib/os-release exists? In my environment, /usr/lib/os-release is present. If /usr/lib/os-release is always present, we don't need to check ${arch}-bottlerocket-linux-gnu/sys-root/usr/lib/os-release.

[root@admin]# ls -alh /.bottlerocket/rootfs/usr/lib/os-release
-rw-r--r--. 1 root root 455 Apr 23 00:29 /.bottlerocket/rootfs/usr/lib/os-release
[root@admin]# cat /.bottlerocket/rootfs/usr/lib/os-release
NAME=Bottlerocket
ID=bottlerocket
VERSION="1.37.0 (aws-k8s-1.30)"
PRETTY_NAME="Bottlerocket OS 1.37.0 (aws-k8s-1.30)"
VARIANT_ID=aws-k8s-1.30
VERSION_ID=1.37.0
BUILD_ID=e5290cd7
VENDOR_NAME="Bottlerocket"
HOME_URL="https://github.com/bottlerocket-os/bottlerocket"
SUPPORT_URL="https://github.com/bottlerocket-os/bottlerocket/discussions"
BUG_REPORT_URL="https://github.com/bottlerocket-os/bottlerocket/issues"
DOCUMENTATION_URL="https://bottlerocket.dev"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, ${arch}-bottlerocket-linux-gnu/sys-root/usr/lib/os-release is mounted to /usr/lib/os-release at run time. When Bottlerocket is running, you can access to /usr/lib/os-release, but when mounting the Bottlerocket partition, you only have access to ${arch}-bottlerocket-linux-gnu/sys-root/usr/lib/os-release. I'm using Trivy in this later case.

Comment on lines 74 to 83
pkg := types.Package{
Arch: app.Architecture,
Name: app.Name,
Version: app.Version,
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

We also need epoch. Otherwise, it leads to false detection.

    {
      "Name": "xfscli",
      "Publisher": "bottlerocket-core-kit",
      "Version": "0.0",
      "Release": "1.1745352352.c92146c5.br1",
      "Epoch": "1",
      "InstalledTime": "2025-04-23T00:26:38Z",
      "ApplicationType": "Unspecified",
      "Architecture": "x86_64",
      "Url": "https://github.com/bottlerocket-os/bottlerocket",
      "Summary": "XFS progs cli"
    },

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've just added handling of epoch.

@0intro 0intro force-pushed the djc/analyzer-bottlerocket branch from 5cc52ee to da46f44 Compare May 12, 2025 12:19
@0intro 0intro requested a review from knqyf263 May 12, 2025 12:34
Copy link
Collaborator

@knqyf263 knqyf263 left a comment

Choose a reason for hiding this comment

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

@DmitriyLewen Can you also take a look?

Copy link
Contributor

@DmitriyLewen DmitriyLewen left a comment

Choose a reason for hiding this comment

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

LGTM
left small comments about comments, tests and purl package

@0intro and can you fix linter errors (mage lint:fix and mage lint:run commands help you)?

return &Scanner{}
}

// Detect vulnerabilities in package using Bottlerocket scanner
Copy link
Contributor

Choose a reason for hiding this comment

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

This is incorrect, because we don't detect vulns for Bottlerocket pkgs.

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.

}

// Detect vulnerabilities in package using Bottlerocket scanner
func (s *Scanner) Detect(ctx context.Context, osVer string, repo *ftypes.Repository, pkgs []ftypes.Package) ([]types.DetectedVulnerability, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's add Info log that Trivy currently doesn't support vulnerability detection for Bottlerocket packages.

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.

pkg/purl/purl.go Outdated
Comment on lines 46 to 48
// Temporary type before being added in github.com/package-url/packageurl-go
packageurlTypeBottlerocket = "bottlerocket"
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// Temporary type before being added in github.com/package-url/packageurl-go
packageurlTypeBottlerocket = "bottlerocket"
// Temporary type before being added in github.com/package-url/packageurl-go
// cf. https://github.com/package-url/purl-spec/issues/454
packageurlTypeBottlerocket = "bottlerocket"

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.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add small test case for bottlerrocker os-release file?

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.

Copy link
Contributor

Choose a reason for hiding this comment

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

I wrote 2 tests for your changes:

diff --git a/pkg/purl/purl_test.go b/pkg/purl/purl_test.go
index 5607551da..ae00df05d 100644
--- a/pkg/purl/purl_test.go
+++ b/pkg/purl/purl_test.go
@@ -440,6 +440,38 @@ func TestNewPackageURL(t *testing.T) {
 				},
 			},
 		},
+		{
+			name: "bottlerocket package",
+			typ:  ftypes.Bottlerocket,
+			metadata: types.Metadata{
+				OS: &ftypes.OS{
+					Family: ftypes.Bottlerocket,
+					Name:   "v1.39.0",
+				},
+			},
+			pkg: ftypes.Package{
+				ID:      "[email protected]",
+				Name:    "glibc",
+				Version: "2.40",
+				Epoch:   1,
+				Arch:    "x86_64",
+			},
+			want: &purl.PackageURL{
+				Type:    "bottlerocket",
+				Name:    "glibc",
+				Version: "2.40",
+				Qualifiers: packageurl.Qualifiers{
+					{
+						Key:   "epoch",
+						Value: "1",
+					},
+					{
+						Key:   "distro",
+						Value: "bottlerocket-v1.39.0",
+					},
+				},
+			},
+		},
 	}
 
 	for _, tc := range testCases {
@@ -710,6 +742,47 @@ func TestPackageURL_Package(t *testing.T) {
 				},
 			},
 		},
+		{
+			name: "bottlerocker with epoch",
+			pkgURL: &purl.PackageURL{
+				Type:    "bottlerocket",
+				Name:    "glibc",
+				Version: "2.40",
+				Qualifiers: packageurl.Qualifiers{
+					{
+						Key:   "epoch",
+						Value: "1",
+					},
+					{
+						Key:   "distro",
+						Value: "bottlerocket-v1.39.0",
+					},
+				},
+			},
+			wantPkg: &ftypes.Package{
+				ID:      "[email protected]",
+				Name:    "glibc",
+				Version: "2.40",
+				Epoch:   1,
+				Identifier: ftypes.PkgIdentifier{
+					PURL: &packageurl.PackageURL{
+						Type:    "bottlerocket",
+						Name:    "glibc",
+						Version: "2.40",
+						Qualifiers: packageurl.Qualifiers{
+							{
+								Key:   "epoch",
+								Value: "1",
+							},
+							{
+								Key:   "distro",
+								Value: "bottlerocket-v1.39.0",
+							},
+						},
+					},
+				},
+			},
+		},
 		{
 			name: "wrong epoch",
 			pkgURL: &purl.PackageURL{

Can you add these tests and update purl package (add epoch)?

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.

@@ -80,6 +83,10 @@ func New(t ftypes.TargetType, metadata types.Metadata, pkg ftypes.Package) (*Pac
if metadata.OS != nil {
namespace = string(metadata.OS.Family)
}
case packageurlTypeBottlerocket:
Copy link
Contributor

Choose a reason for hiding this comment

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

Add bottlerocker into purlType(t) function:

diff --git a/pkg/purl/purl.go b/pkg/purl/purl.go
index c0287cca6..7c59ff4f4 100644
--- a/pkg/purl/purl.go
+++ b/pkg/purl/purl.go
@@ -7,7 +7,7 @@ import (
 
        cn "github.com/google/go-containerregistry/pkg/name"
        version "github.com/knqyf263/go-rpm-version"
-       packageurl "github.com/package-url/packageurl-go"
+       "github.com/package-url/packageurl-go"
        "github.com/samber/lo"
        "golang.org/x/xerrors"
 
@@ -489,6 +489,8 @@ func purlType(t ftypes.TargetType) string {
                ftypes.OpenSUSELeap, ftypes.OpenSUSETumbleweed, ftypes.SLES, ftypes.SLEMicro, ftypes.Photon,
                ftypes.Azure, ftypes.CBLMariner:
                return packageurl.TypeRPM
+       case ftypes.Bottlerocket:
+               return packageurlTypeBottlerocket
        case TypeOCI:
                return packageurl.TypeOCI
        case ftypes.Julia:

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.

@0intro 0intro force-pushed the djc/analyzer-bottlerocket branch from da46f44 to 2197941 Compare May 19, 2025 13:49
@0intro 0intro requested review from DmitriyLewen and knqyf263 May 19, 2025 13:50
@0intro
Copy link
Contributor Author

0intro commented May 19, 2025

Thanks. I think I've done all the required changes.

@0intro 0intro force-pushed the djc/analyzer-bottlerocket branch from 2197941 to ff5f568 Compare May 19, 2025 13:52
Copy link
Contributor

@DmitriyLewen DmitriyLewen left a comment

Choose a reason for hiding this comment

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

@0intro Thanks for your work!
LGTM.

I left 1 comment.
And you need to update docs (OS page):
https://trivy.dev/latest/docs/coverage/os/

PS use mage docs:serve to see your changes

PS2 fix linter errors please

@0intro 0intro force-pushed the djc/analyzer-bottlerocket branch 3 times, most recently from dc913f1 to e4fd63a Compare May 21, 2025 07:34
@0intro
Copy link
Contributor Author

0intro commented May 21, 2025

I've added the documentation.

@DmitriyLewen
Copy link
Contributor

@0intro Great!
run mage lint:fix please.

This change adds the Bottlerocket OS package analyzer.

This analyzer parses the package information provided in the
application-inventory.json file, as specified on:

https://bottlerocket.dev/en/os/1.37.x/concepts/variants/#software-inventory

This change also defines the Bottlerocket OS family.
@0intro 0intro force-pushed the djc/analyzer-bottlerocket branch from e4fd63a to f9345fb Compare May 23, 2025 06:00
@0intro 0intro requested a review from DmitriyLewen May 23, 2025 06:01
Copy link
Contributor

@DmitriyLewen DmitriyLewen left a comment

Choose a reason for hiding this comment

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

LGTM
@0intro Thanks for your contribution!

cc. @knqyf263

@knqyf263 knqyf263 added this pull request to the merge queue May 23, 2025
Merged via the queue into aquasecurity:main with commit 07ef63b May 23, 2025
17 checks passed
0intro added a commit to DataDog/trivy that referenced this pull request May 26, 2025
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.

3 participants