Compare commits

...

5 Commits

Author SHA1 Message Date
Aqua Security automated builds
86ee3c1176 release: v0.64.1 [release/v0.64] (#9122) 2025-07-03 13:18:35 +00:00
Aqua Security automated builds
4e1272283a fix(misconf): skip rewriting expr if attr is nil [backport: release/v0.64] (#9127)
Signed-off-by: nikpivkin <nikita.pivkin@smartforce.io>
Co-authored-by: Nikita Pivkin <nikita.pivkin@smartforce.io>
2025-07-03 06:42:19 +00:00
Aqua Security automated builds
9a7d38432c fix(cli): Add more non-sensitive flags to telemetry [backport: release/v0.64] (#9124)
Co-authored-by: Owen Rumney <owen.rumney@aquasec.com>
2025-07-02 11:20:33 +00:00
Aqua Security automated builds
53adfba3c2 fix(rootio): check full version to detect root.io packages [backport: release/v0.64] (#9120)
Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com>
2025-07-02 10:29:38 +00:00
Aqua Security automated builds
8cf1bf9f6f fix(alma): parse epochs from rpmqa file [backport: release/v0.64] (#9119)
Co-authored-by: Tom Fay <tom@teamfay.co.uk>
2025-07-02 09:41:53 +00:00
21 changed files with 194 additions and 71 deletions

View File

@@ -67,6 +67,7 @@ jobs:
distroless
windows
minimos
rootio
# Languages
ruby

View File

@@ -1 +1 @@
{".":"0.64.0"}
{".":"0.64.1"}

View File

@@ -1,5 +1,15 @@
# Changelog
## [0.64.1](https://github.com/aquasecurity/trivy/compare/v0.64.0...v0.64.1) (2025-07-03)
### Bug Fixes
* **alma:** parse epochs from rpmqa file [backport: release/v0.64] ([#9119](https://github.com/aquasecurity/trivy/issues/9119)) ([8cf1bf9](https://github.com/aquasecurity/trivy/commit/8cf1bf9f6f86936ee7dcd29e0d1cd1ec106e28f6))
* **cli:** Add more non-sensitive flags to telemetry [backport: release/v0.64] ([#9124](https://github.com/aquasecurity/trivy/issues/9124)) ([9a7d384](https://github.com/aquasecurity/trivy/commit/9a7d38432cf00f00970259e5ac3edd060e00ccff))
* **misconf:** skip rewriting expr if attr is nil [backport: release/v0.64] ([#9127](https://github.com/aquasecurity/trivy/issues/9127)) ([4e12722](https://github.com/aquasecurity/trivy/commit/4e1272283a643bfca2d7231d286006219715fada))
* **rootio:** check full version to detect `root.io` packages [backport: release/v0.64] ([#9120](https://github.com/aquasecurity/trivy/issues/9120)) ([53adfba](https://github.com/aquasecurity/trivy/commit/53adfba3c25664b01e3a36fdec334b39b53c07f1))
## [0.64.0](https://github.com/aquasecurity/trivy/compare/v0.63.0...v0.64.0) (2025-06-30)

View File

@@ -1,19 +1,40 @@
```
--clear-cache
--debug
--dependency-tree
--detection-priority
--distro
--exit-code
--exit-on-eol
--format
--ignore-status
--ignore-unfixed
--image-config-scanners
--include-deprecated-checks
--include-dev-deps
--include-non-failures
--insecure
--license-full
--list-all-pkgs
--misconfig-scanners
--offline-scan
--parallel
--password-stdin
--pkg-relationships
--pkg-types
--quiet
--redis-tls
--removed-pkgs
--report
--scanners
--severity
--show-suppressed
--skip-check-update
--skip-version-check
--skip-vex-repo-update
--slow
--tf-exclude-downloaded-modules
--timeout
--trace
--vuln-severity-source
```

View File

@@ -5,6 +5,7 @@ import (
"github.com/aquasecurity/trivy/pkg/detector/ospkg/driver"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/scan/utils"
)
var (
@@ -37,7 +38,7 @@ func isRootIOEnvironment(osFamily ftypes.OSType, pkgs []ftypes.Package) bool {
// hasPackageWithPattern checks if any package version matches the specified pattern
func hasPackageWithPattern(pkgs []ftypes.Package, pattern *regexp.Regexp) bool {
for _, pkg := range pkgs {
if pattern.MatchString(pkg.Version) {
if pattern.MatchString(utils.FormatVersion(pkg)) {
return true
}
}

View File

@@ -21,7 +21,7 @@ func TestProvider(t *testing.T) {
name: "Debian with .root.io package",
osFamily: ftypes.Debian,
pkgs: []ftypes.Package{
{Name: "libc6", Version: "2.31-13+deb11u4.root.io"},
{Name: "libc6", Version: "2.31", Release: "13+deb11u4.root.io"},
{Name: "bash", Version: "5.1-2+deb11u1"},
},
want: true,

View File

@@ -5,6 +5,7 @@ import (
"context"
"os"
"slices"
"strconv"
"strings"
"golang.org/x/xerrors"
@@ -50,6 +51,7 @@ func (a rpmqaPkgAnalyzer) parseRpmqaManifest(r xio.ReadSeekerAt) ([]types.Packag
for scanner.Scan() {
line := scanner.Text()
var name, ver, rel, sourceRpm, arch string
var epoch int
// %{NAME}\t%{VERSION}-%{RELEASE}\t%{INSTALLTIME}\t%{BUILDTIME}\t%{VENDOR}\t(none)\t%{SIZE}\t%{ARCH}\t%{EPOCHNUM}\t%{SOURCERPM}
s := strings.Split(line, "\t")
if len(s) != 10 {
@@ -68,12 +70,18 @@ func (a rpmqaPkgAnalyzer) parseRpmqaManifest(r xio.ReadSeekerAt) ([]types.Packag
if err != nil {
return nil, xerrors.Errorf("failed to split source rpm: %w", err)
}
epoch, err = strconv.Atoi(s[8])
if err != nil {
return nil, xerrors.Errorf("failed to parse epoch number (%s): %w", s[8], err)
}
pkgs = append(pkgs, types.Package{
Name: name,
Version: ver,
Epoch: epoch,
Release: rel,
Arch: arch,
SrcName: srcName,
SrcEpoch: epoch,
SrcVersion: srcVer,
SrcRelease: srcRel,
})

View File

@@ -21,7 +21,8 @@ func TestParseMarinerDistrolessManifest(t *testing.T) {
name: "happy path",
content: `mariner-release 2.0-12.cm2 1653816591 1653753130 Microsoft Corporation (none) 580 noarch 0 mariner-release-2.0-12.cm2.src.rpm
filesystem 1.1-9.cm2 1653816591 1653628924 Microsoft Corporation (none) 7596 x86_64 0 filesystem-1.1-9.cm2.src.rpm
glibc 2.35-2.cm2 1653816591 1653628955 Microsoft Corporation (none) 10855265 x86_64 0 glibc-2.35-2.cm2.src.rpm`,
glibc 2.35-2.cm2 1653816591 1653628955 Microsoft Corporation (none) 10855265 x86_64 0 glibc-2.35-2.cm2.src.rpm
ca-certificates-base 3.0.0-8.azl3 1748892790 1735838940 Microsoft Corporation (none) 130628 noarch 1 ca-certificates-3.0.0-8.azl3.src.rpm`,
wantPkgs: []types.Package{
{
Name: "mariner-release",
@@ -50,6 +51,17 @@ glibc 2.35-2.cm2 1653816591 1653628955 Microsoft Corporation (none) 10855265 x86
SrcVersion: "2.35",
SrcRelease: "2.cm2",
},
{
Name: "ca-certificates-base",
Version: "3.0.0",
Epoch: 1,
Release: "8.azl3",
Arch: "noarch",
SrcName: "ca-certificates",
SrcEpoch: 1,
SrcVersion: "3.0.0",
SrcRelease: "8.azl3",
},
},
},
{

View File

@@ -16,10 +16,11 @@ import (
var (
// Deprecated
ClearCacheFlag = Flag[bool]{
Name: "clear-cache",
ConfigName: "cache.clear",
Usage: "clear image caches without scanning",
Removed: `Use "trivy clean --scan-cache" instead`,
Name: "clear-cache",
ConfigName: "cache.clear",
Usage: "clear image caches without scanning",
Removed: `Use "trivy clean --scan-cache" instead`,
TelemetrySafe: true,
}
CacheBackendFlag = Flag[string]{
Name: "cache-backend",
@@ -33,9 +34,10 @@ var (
Usage: "cache TTL when using redis as cache backend",
}
RedisTLSFlag = Flag[bool]{
Name: "redis-tls",
ConfigName: "cache.redis.tls",
Usage: "enable redis TLS with public certificates, if using redis as cache backend",
Name: "redis-tls",
ConfigName: "cache.redis.tls",
Usage: "enable redis TLS with public certificates, if using redis as cache backend",
TelemetrySafe: true,
}
RedisCACertFlag = Flag[string]{
Name: "redis-ca",

View File

@@ -23,12 +23,14 @@ var (
types.MisconfigScanner,
types.SecretScanner,
}),
Usage: "comma-separated list of what security issues to detect on container image configurations",
Usage: "comma-separated list of what security issues to detect on container image configurations",
TelemetrySafe: true,
}
ScanRemovedPkgsFlag = Flag[bool]{
Name: "removed-pkgs",
ConfigName: "image.removed-pkgs",
Usage: "detect vulnerabilities of removed packages (only for Alpine)",
Name: "removed-pkgs",
ConfigName: "image.removed-pkgs",
Usage: "detect vulnerabilities of removed packages (only for Alpine)",
TelemetrySafe: true,
}
InputFlag = Flag[string]{
Name: "input",

View File

@@ -7,9 +7,10 @@ import (
var (
LicenseFull = Flag[bool]{
Name: "license-full",
ConfigName: "license.full",
Usage: "eagerly look for licenses in source code headers and license files",
Name: "license-full",
ConfigName: "license.full",
Usage: "eagerly look for licenses in source code headers and license files",
TelemetrySafe: true,
}
IgnoredLicenses = Flag[[]string]{
Name: "ignored-licenses",

View File

@@ -33,9 +33,10 @@ var (
},
}
IncludeNonFailuresFlag = Flag[bool]{
Name: "include-non-failures",
ConfigName: "misconfiguration.include-non-failures",
Usage: "include successes, available with '--scanners misconfig'",
Name: "include-non-failures",
ConfigName: "misconfiguration.include-non-failures",
Usage: "include successes, available with '--scanners misconfig'",
TelemetrySafe: true,
}
HelmValuesFileFlag = Flag[[]string]{
Name: "helm-values",
@@ -79,9 +80,10 @@ var (
Usage: "specify paths to override the CloudFormation parameters files",
}
TerraformExcludeDownloaded = Flag[bool]{
Name: "tf-exclude-downloaded-modules",
ConfigName: "misconfiguration.terraform.exclude-downloaded-modules",
Usage: "exclude misconfigurations for downloaded terraform modules",
Name: "tf-exclude-downloaded-modules",
ConfigName: "misconfiguration.terraform.exclude-downloaded-modules",
Usage: "exclude misconfigurations for downloaded terraform modules",
TelemetrySafe: true,
}
ChecksBundleRepositoryFlag = Flag[string]{
Name: "checks-bundle-repository",

View File

@@ -22,9 +22,10 @@ var (
Usage: "password. Comma-separated passwords allowed. TRIVY_PASSWORD should be used for security reasons.",
}
PasswordStdinFlag = Flag[bool]{
Name: "password-stdin",
ConfigName: "registry.password-stdin",
Usage: "password from stdin. Comma-separated passwords are not supported.",
Name: "password-stdin",
ConfigName: "registry.password-stdin",
Usage: "password from stdin. Comma-separated passwords are not supported.",
TelemetrySafe: true,
}
RegistryTokenFlag = Flag[string]{
Name: "registry-token",

View File

@@ -8,9 +8,10 @@ package flag
// policy-namespaces: "user"
var (
IncludeDeprecatedChecksFlag = Flag[bool]{
Name: "include-deprecated-checks",
ConfigName: "rego.include-deprecated-checks",
Usage: "include deprecated checks",
Name: "include-deprecated-checks",
ConfigName: "rego.include-deprecated-checks",
Usage: "include deprecated checks",
TelemetrySafe: true,
}
SkipCheckUpdateFlag = Flag[bool]{
Name: "skip-check-update",
@@ -23,11 +24,13 @@ var (
Deprecated: true,
},
},
TelemetrySafe: true,
}
TraceFlag = Flag[bool]{
Name: "trace",
ConfigName: "rego.trace",
Usage: "enable more verbose trace output for custom queries",
Name: "trace",
ConfigName: "rego.trace",
Usage: "enable more verbose trace output for custom queries",
TelemetrySafe: true,
}
ConfigCheckFlag = Flag[[]string]{
Name: "config-check",

View File

@@ -52,9 +52,10 @@ var (
Usage: "output template",
}
DependencyTreeFlag = Flag[bool]{
Name: "dependency-tree",
ConfigName: "dependency-tree",
Usage: "[EXPERIMENTAL] show dependency origin tree of vulnerable packages",
Name: "dependency-tree",
ConfigName: "dependency-tree",
Usage: "[EXPERIMENTAL] show dependency origin tree of vulnerable packages",
TelemetrySafe: true,
}
ListAllPkgsFlag = Flag[bool]{
Name: "list-all-pkgs",
@@ -74,14 +75,16 @@ var (
Usage: "specify the Rego file path to evaluate each vulnerability",
}
ExitCodeFlag = Flag[int]{
Name: "exit-code",
ConfigName: "exit-code",
Usage: "specify exit code when any security issues are found",
Name: "exit-code",
ConfigName: "exit-code",
Usage: "specify exit code when any security issues are found",
TelemetrySafe: true,
}
ExitOnEOLFlag = Flag[int]{
Name: "exit-on-eol",
ConfigName: "exit-on-eol",
Usage: "exit with the specified code when the OS reaches end of service/life",
Name: "exit-on-eol",
ConfigName: "exit-on-eol",
Usage: "exit with the specified code when the OS reaches end of service/life",
TelemetrySafe: true,
}
OutputFlag = Flag[string]{
Name: "output",

View File

@@ -27,9 +27,10 @@ var (
Usage: "specify the files or glob patterns to skip",
}
OfflineScanFlag = Flag[bool]{
Name: "offline-scan",
ConfigName: "scan.offline",
Usage: "do not issue API requests to identify dependencies",
Name: "offline-scan",
ConfigName: "scan.offline",
Usage: "do not issue API requests to identify dependencies",
TelemetrySafe: true,
}
ScannersFlag = Flag[[]string]{
Name: "scanners",
@@ -74,17 +75,19 @@ var (
Usage: "specify config file patterns",
}
SlowFlag = Flag[bool]{
Name: "slow",
ConfigName: "scan.slow",
Default: false,
Usage: "scan over time with lower CPU and memory utilization",
Deprecated: `Use "--parallel 1" instead.`,
Name: "slow",
ConfigName: "scan.slow",
Default: false,
Usage: "scan over time with lower CPU and memory utilization",
Deprecated: `Use "--parallel 1" instead.`,
TelemetrySafe: true,
}
ParallelFlag = Flag[int]{
Name: "parallel",
ConfigName: "scan.parallel",
Default: 5,
Usage: "number of goroutines enabled for parallel scanning, set 0 to auto-detect parallelism",
Name: "parallel",
ConfigName: "scan.parallel",
Default: 5,
Usage: "number of goroutines enabled for parallel scanning, set 0 to auto-detect parallelism",
TelemetrySafe: true,
}
SBOMSourcesFlag = Flag[[]string]{
Name: "sbom-sources",
@@ -116,14 +119,16 @@ var (
TelemetrySafe: true,
}
DistroFlag = Flag[string]{
Name: "distro",
ConfigName: "scan.distro",
Usage: "[EXPERIMENTAL] specify a distribution, <family>/<version>",
Name: "distro",
ConfigName: "scan.distro",
Usage: "[EXPERIMENTAL] specify a distribution, <family>/<version>",
TelemetrySafe: true,
}
SkipVersionCheckFlag = Flag[bool]{
Name: "skip-version-check",
ConfigName: "scan.skip-version-check",
Usage: "suppress notices about version updates and Trivy announcements",
Name: "skip-version-check",
ConfigName: "scan.skip-version-check",
Usage: "suppress notices about version updates and Trivy announcements",
TelemetrySafe: true,
}
DisableTelemetryFlag = Flag[bool]{
Name: "disable-telemetry",

View File

@@ -12,9 +12,10 @@ import (
var (
IgnoreUnfixedFlag = Flag[bool]{
Name: "ignore-unfixed",
ConfigName: "vulnerability.ignore-unfixed",
Usage: "display only fixed vulnerabilities",
Name: "ignore-unfixed",
ConfigName: "vulnerability.ignore-unfixed",
Usage: "display only fixed vulnerabilities",
TelemetrySafe: true,
}
IgnoreStatusFlag = Flag[[]string]{
Name: "ignore-status",
@@ -29,9 +30,10 @@ var (
Usage: `[EXPERIMENTAL] VEX sources ("repo", "oci" or file path)`,
}
SkipVEXRepoUpdateFlag = Flag[bool]{
Name: "skip-vex-repo-update",
ConfigName: "vulnerability.skip-vex-repo-update",
Usage: `[EXPERIMENTAL] Skip VEX Repository update`,
Name: "skip-vex-repo-update",
ConfigName: "vulnerability.skip-vex-repo-update",
Usage: `[EXPERIMENTAL] Skip VEX Repository update`,
TelemetrySafe: true,
}
VulnSeveritySourceFlag = Flag[[]string]{
Name: "vuln-severity-source",

View File

@@ -17,6 +17,11 @@ type wrappedDocument struct {
}
func ParsePolicyFromAttr(attr *terraform.Attribute, owner *terraform.Block, modules terraform.Modules) (*iam.Document, error) {
if attr == nil {
return &iam.Document{
Metadata: owner.GetMetadata(),
}, nil
}
attr.RewriteExpr(func(e hclsyntax.Expression) hclsyntax.Expression {
if te, ok := e.(*hclsyntax.TemplateExpr); ok {
return &terraform.PartialTemplateExpr{TemplateExpr: te}

View File

@@ -1,6 +1,8 @@
package iam
import (
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/aquasecurity/iamgo"
"github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam"
"github.com/aquasecurity/trivy/pkg/iac/terraform"
@@ -140,11 +142,20 @@ func findAttachmentPolicy(modules terraform.Modules) func(resource *terraform.Bl
}
}
if block, err := modules.GetReferencedBlock(attr, resource); err == nil {
return findPolicy(modules)(block)
// Searching for a referenced block only makes sense for traversal expressions,
// since only they can directly reference other blocks in the configuration.
switch attr.HCLAttribute().Expr.(type) {
case *hclsyntax.RelativeTraversalExpr, *hclsyntax.ScopeTraversalExpr:
if block, err := modules.GetReferencedBlock(attr, resource); err == nil {
return findPolicy(modules)(block)
}
}
return &iam.Policy{
Metadata: resource.GetMetadata(),
Document: iam.Document{
Metadata: resource.GetMetadata(),
},
}
return nil
}
}

View File

@@ -338,6 +338,32 @@ resource "aws_iam_role_policy_attachment" "test" {
},
},
},
{
name: "policy is template with unknown part",
terraform: `resource "aws_iam_role" "default" {
name = "test"
}
resource "aws_iam_role_policy_attachment" "amazon_eks_cluster_policy" {
role = aws_iam_role.default.name
policy_arn = format("arn:%s:iam::aws:policy/AmazonEKSClusterPolicy", data.aws_partition.current.partition)
}
data "aws_partition" "current" {}
`,
expected: []iam.Role{
{
Name: iacTypes.StringTest("test"),
Policies: []iam.Policy{
{
Name: iacTypes.StringTest(""),
Document: iam.Document{},
},
},
},
},
},
}
for _, test := range tests {

View File

@@ -834,7 +834,14 @@ func safeOp[T any](a *Attribute, fn func(cty.Value) T) T {
// RewriteExpr applies the given function `transform` to the expression of the attribute,
// recursively traversing and transforming it.
func (a *Attribute) RewriteExpr(transform func(hclsyntax.Expression) hclsyntax.Expression) {
a.hclAttribute.Expr = RewriteExpr(a.hclAttribute.Expr.(hclsyntax.Expression), transform)
if a == nil || a.hclAttribute == nil {
return
}
expr, ok := a.hclAttribute.Expr.(hclsyntax.Expression)
if !ok {
return
}
a.hclAttribute.Expr = RewriteExpr(expr, transform)
}
// nolint: gocyclo