fix: prevent redis classifier from detecting valkey (#4619)

Signed-off-by: witchcraze <witchcraze@gmail.com>
This commit is contained in:
witchcraze 2026-05-05 03:07:29 +09:00 committed by GitHub
parent 1e4f424f09
commit 514efb03e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 67 additions and 8 deletions

View File

@ -106,7 +106,12 @@ func DefaultClassifiers() []binutils.Classifier {
{ {
Class: "redis-binary", Class: "redis-binary",
FileGlob: "**/redis-server", FileGlob: "**/redis-server",
EvidenceMatcher: binutils.MatchAny( EvidenceMatcher: binutils.MatchAll(
// Negative Matchers to exclude valkey-server
binutils.MatchNone(
binutils.MatchPath("**/valkey-server"),
),
binutils.MatchAny(
// matches most recent versions of redis (~v7), e.g. "7.0.14buildkitsandbox-1702957741000000000" // matches most recent versions of redis (~v7), e.g. "7.0.14buildkitsandbox-1702957741000000000"
m.FileContentsVersionMatcher(`[^\d](?P<version>\d+.\d+\.\d+)buildkitsandbox-\d+`), m.FileContentsVersionMatcher(`[^\d](?P<version>\d+.\d+\.\d+)buildkitsandbox-\d+`),
// matches against older versions of redis (~v3 - v6), e.g. "4.0.11841ce7054bd9-1542359302000000000" // matches against older versions of redis (~v3 - v6), e.g. "4.0.11841ce7054bd9-1542359302000000000"
@ -114,6 +119,7 @@ func DefaultClassifiers() []binutils.Classifier {
// matches against older versions of redis (~v2), e.g. "Server started, Redis version 2.8.23" // matches against older versions of redis (~v2), e.g. "Server started, Redis version 2.8.23"
m.FileContentsVersionMatcher(`Redis version (?P<version>[0-9]+\.[0-9]+\.[0-9]+)`), m.FileContentsVersionMatcher(`Redis version (?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
), ),
),
Package: "redis", Package: "redis",
PURL: mustPURL("pkg:generic/redis@version"), PURL: mustPURL("pkg:generic/redis@version"),
CPEs: []cpe.CPE{ CPEs: []cpe.CPE{

View File

@ -625,12 +625,14 @@ from-images:
paths: paths:
- /usr/local/bin/redis-server - /usr/local/bin/redis-server
- version: 9.0.0 - name: valkey-server
version: 9.0.0
images: images:
- ref: valkey/valkey:9.0.0@sha256:42ea97850708540d4e05f6241cfbd241c1ba502e64d9a42efb2c2e277a8ca9d6 - ref: valkey/valkey:9.0.0@sha256:42ea97850708540d4e05f6241cfbd241c1ba502e64d9a42efb2c2e277a8ca9d6
platform: linux/amd64 platform: linux/amd64
paths: paths:
- /usr/local/bin/valkey-server - /usr/local/bin/valkey-server
- /usr/local/bin/redis-server
- version: 2.9.0 - version: 2.9.0
images: images:

View File

@ -120,6 +120,20 @@ func MatchAll(matchers ...EvidenceMatcher) EvidenceMatcher {
} }
} }
// MatchNone succeeds only if the matcher returns no results.
func MatchNone(matcher EvidenceMatcher) EvidenceMatcher {
return func(classifier Classifier, context MatcherContext) ([]pkg.Package, error) {
match, err := matcher(classifier, context)
if err != nil {
return nil, err
}
if match != nil {
return nil, nil
}
return []pkg.Package{}, nil
}
}
type ContextualEvidenceMatchers struct { type ContextualEvidenceMatchers struct {
CatalogerName string CatalogerName string
} }

View File

@ -243,3 +243,40 @@ func Test_SupportingEvidenceMatcher(t *testing.T) {
}) })
} }
} }
func TestMatchNone(t *testing.T) {
matchingMatcher := MatchPath("**")
notMatchingMatcher := MatchPath("will-not-match")
tests := []struct {
name string
matcher EvidenceMatcher
expected bool // true if MatchNone should succeed (inner failed)
}{
{
name: "inner matches, MatchNone fails",
matcher: MatchNone(matchingMatcher),
expected: false,
},
{
name: "inner fails, MatchNone succeeds",
matcher: MatchNone(notMatchingMatcher),
expected: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pkgs, err := tt.matcher(Classifier{}, MatcherContext{
Location: file.NewLocation("some/path"),
})
require.NoError(t, err)
if tt.expected {
assert.NotNil(t, pkgs)
assert.Empty(t, pkgs)
} else {
assert.Nil(t, pkgs)
}
})
}
}