From f69b1db099032be375a43963db8f81f6cb12e220 Mon Sep 17 00:00:00 2001 From: Rez Moss Date: Thu, 6 Nov 2025 16:02:02 -0500 Subject: [PATCH] feat: detect elixir bin (#4334) * Elixir detection, fixed #4333 --------- Signed-off-by: Rez Moss --- .../binary/classifier_cataloger_test.go | 16 +++++++++++++++ syft/pkg/cataloger/binary/classifiers.go | 20 +++++++++++++++++++ .../snippets/elixir/1.19.1/linux-amd64/elixir | 20 +++++++++++++++++++ .../linux-amd64/lib/elixir/ebin/elixir.app | 19 ++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/elixir/1.19.1/linux-amd64/elixir create mode 100644 syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/elixir/1.19.1/linux-amd64/lib/elixir/ebin/elixir.app diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index 055672b25..4cd12f4df 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -1403,6 +1403,22 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("ffmpeg-library"), }, }, + { + logicalFixture: "elixir/1.19.1/linux-amd64", + expected: pkg.Package{ + Name: "elixir", + Version: "1.19.1", + Type: "binary", + PURL: "pkg:generic/elixir@1.19.1", + Locations: locations("elixir", "lib/elixir/ebin/elixir.app"), + Metadata: pkg.BinarySignature{ + Matches: []pkg.ClassifierMatch{ + match("elixir-binary", "elixir"), + match("elixir-library", "lib/elixir/ebin/elixir.app"), + }, + }, + }, + }, } for _, test := range tests { diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index a58091c6b..c3480aac8 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -663,6 +663,26 @@ func DefaultClassifiers() []binutils.Classifier { PURL: mustPURL("pkg:generic/ffmpeg@version"), CPEs: singleCPE("cpe:2.3:a:ffmpeg:ffmpeg:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, + { + Class: "elixir-binary", + FileGlob: "**/elixir", + EvidenceMatcher: m.FileContentsVersionMatcher( + `(?m)ELIXIR_VERSION=(?P[0-9]+\.[0-9]+\.[0-9]+)`), + Package: "elixir", + PURL: mustPURL("pkg:generic/elixir@version"), + CPEs: []cpe.CPE{ + cpe.Must("cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + }, + { + Class: "elixir-library", + FileGlob: "**/elixir/ebin/elixir.app", + EvidenceMatcher: m.FileContentsVersionMatcher( + `(?m)\{vsn,"(?P[0-9]+\.[0-9]+\.[0-9]+(-[a-z0-9]+)?)"\}`), + Package: "elixir", + PURL: mustPURL("pkg:generic/elixir@version"), + CPEs: singleCPE("cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, } return append(classifiers, defaultJavaClassifiers()...) diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/elixir/1.19.1/linux-amd64/elixir b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/elixir/1.19.1/linux-amd64/elixir new file mode 100644 index 000000000..4903259c4 --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/elixir/1.19.1/linux-amd64/elixir @@ -0,0 +1,20 @@ +#!/bin/sh + +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: 2021 The Elixir Team +# SPDX-FileCopyrightText: 2012 Plataformatec + +set -e + +ELIXIR_VERSION=1.19.1 + +if [ $# -eq 0 ] || { [ $# -eq 1 ] && { [ "$1" = "--help" ] || [ "$1" = "-h" ]; }; }; then + cat <&2 +Usage: $(basename "$0") [options] [.exs file] [data] + +## General options + + -e "COMMAND" Evaluates the given command (*) + -h, --help Prints this message (standalone) + -r "FILE" Requires the given files/patterns (*) + -S SCRIPT Finds and executes the given script in \$PATH diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/elixir/1.19.1/linux-amd64/lib/elixir/ebin/elixir.app b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/elixir/1.19.1/linux-amd64/lib/elixir/ebin/elixir.app new file mode 100644 index 000000000..6d3b3e0be --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/elixir/1.19.1/linux-amd64/lib/elixir/ebin/elixir.app @@ -0,0 +1,19 @@ +{application,elixir, + [{description,"elixir"}, + {vsn,"1.19.1"}, + {modules, + ['Elixir.Access','Elixir.Agent.Server','Elixir.Agent', + 'Elixir.Application','Elixir.ArgumentError', + elixir_overridable,elixir_parser,elixir_quote,elixir_rewrite, + elixir_sup,elixir_tokenizer,elixir_utils,iex]}, + {registered,[elixir_sup,elixir_config,elixir_code_server]}, + {applications,[kernel,stdlib,compiler]}, + {mod,{elixir,[]}}, + {env, + [{ansi_syntax_colors, + [{atom,cyan}, + {binary,default_color}, + {operator,default_color}]}, + {check_endianness,true}, + {dbg_callback,{'Elixir.Macro',dbg,[]}}, + {time_zone_database,'Elixir.Calendar.UTCOnlyTimeZoneDatabase'}]}]}.