mirror of
https://github.com/anchore/syft.git
synced 2026-07-05 02:28:25 +02:00
added macOS .app cataloger (#4490)
* added macOS .app cataloger, fixed #4010 Signed-off-by: Rez Moss <hi@rezmoss.com> Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * added macOS .app cataloger, fixed #4010 Signed-off-by: Rez Moss <hi@rezmoss.com> Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * added macOS .app cataloger, fixed #4010 Signed-off-by: Rez Moss <hi@rezmoss.com> Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * address review comments Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * bump schema to 16.1.7 Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * address static analysis failures Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * migrate to testdata Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * expand fields and improve test coverage Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: Rez Moss <hi@rezmoss.com> Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
parent
deee79411a
commit
148fe572bc
@ -89,6 +89,7 @@ func TestPkgCoverageImage(t *testing.T) {
|
|||||||
definedPkgs.Remove(string(pkg.PhpPeclPkg)) // we have coverage for pear instead
|
definedPkgs.Remove(string(pkg.PhpPeclPkg)) // we have coverage for pear instead
|
||||||
definedPkgs.Remove(string(pkg.CondaPkg))
|
definedPkgs.Remove(string(pkg.CondaPkg))
|
||||||
definedPkgs.Remove(string(pkg.ModelPkg))
|
definedPkgs.Remove(string(pkg.ModelPkg))
|
||||||
|
definedPkgs.Remove(string(pkg.AppleAppBundlePkg))
|
||||||
|
|
||||||
var cases []testCase
|
var cases []testCase
|
||||||
cases = append(cases, commonTestCases...)
|
cases = append(cases, commonTestCases...)
|
||||||
@ -164,6 +165,7 @@ func TestPkgCoverageDirectory(t *testing.T) {
|
|||||||
definedPkgs.Remove(string(pkg.CondaPkg))
|
definedPkgs.Remove(string(pkg.CondaPkg))
|
||||||
definedPkgs.Remove(string(pkg.PhpPeclPkg)) // this is covered as pear packages
|
definedPkgs.Remove(string(pkg.PhpPeclPkg)) // this is covered as pear packages
|
||||||
definedPkgs.Remove(string(pkg.ModelPkg))
|
definedPkgs.Remove(string(pkg.ModelPkg))
|
||||||
|
definedPkgs.Remove(string(pkg.AppleAppBundlePkg))
|
||||||
|
|
||||||
// for directory scans we should not expect to see any of the following package types
|
// for directory scans we should not expect to see any of the following package types
|
||||||
definedPkgs.Remove(string(pkg.KbPkg))
|
definedPkgs.Remove(string(pkg.KbPkg))
|
||||||
|
|||||||
1
go.mod
1
go.mod
@ -104,6 +104,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/pb33f/ordered-map/v2 v2.3.1
|
github.com/pb33f/ordered-map/v2 v2.3.1
|
||||||
github.com/tailscale/hujson v0.0.0-20260302212456-ecc657c15afd
|
github.com/tailscale/hujson v0.0.0-20260302212456-ecc657c15afd
|
||||||
|
howett.net/plist v1.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|||||||
4
go.sum
4
go.sum
@ -626,6 +626,7 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
|
|||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||||
github.com/jedib0t/go-pretty/v6 v6.8.1 h1:0fkCNhjrX0zPpwkWaDYU5VMrygg41Tu197mWILIJoqQ=
|
github.com/jedib0t/go-pretty/v6 v6.8.1 h1:0fkCNhjrX0zPpwkWaDYU5VMrygg41Tu197mWILIJoqQ=
|
||||||
github.com/jedib0t/go-pretty/v6 v6.8.1/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU=
|
github.com/jedib0t/go-pretty/v6 v6.8.1/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU=
|
||||||
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
||||||
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
|
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
@ -1489,6 +1490,7 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
|||||||
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||||
|
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
@ -1509,6 +1511,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
|||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
|
howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=
|
||||||
|
howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
||||||
modernc.org/cc/v4 v4.28.2 h1:3tQ0lf2ADtoby2EtSP+J7IE2SHwEJdP8ioR59wx7XpY=
|
modernc.org/cc/v4 v4.28.2 h1:3tQ0lf2ADtoby2EtSP+J7IE2SHwEJdP8ioR59wx7XpY=
|
||||||
modernc.org/cc/v4 v4.28.2/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
|
modernc.org/cc/v4 v4.28.2/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
|
||||||
modernc.org/ccgo/v4 v4.34.0 h1:yRLPFZieg532OT4rp4JFNIVcquwalMX26G95WQDqwCQ=
|
modernc.org/ccgo/v4 v4.34.0 h1:yRLPFZieg532OT4rp4JFNIVcquwalMX26G95WQDqwCQ=
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package internal
|
|||||||
const (
|
const (
|
||||||
// JSONSchemaVersion is the current schema version output by the JSON encoder
|
// JSONSchemaVersion is the current schema version output by the JSON encoder
|
||||||
// This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
|
// This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
|
||||||
JSONSchemaVersion = "16.1.6"
|
JSONSchemaVersion = "16.1.7"
|
||||||
|
|
||||||
// Changelog
|
// Changelog
|
||||||
// 16.1.0 - reformulated the python pdm fields (added "URL" and removed the unused "path" field).
|
// 16.1.0 - reformulated the python pdm fields (added "URL" and removed the unused "path" field).
|
||||||
@ -13,5 +13,6 @@ const (
|
|||||||
// 16.1.4 - add BunLockEntry metadata type for bun.lock support
|
// 16.1.4 - add BunLockEntry metadata type for bun.lock support
|
||||||
// 16.1.5 - add DenoLockEntry and DenoRemoteLockEntry metadata types for deno.lock support
|
// 16.1.5 - add DenoLockEntry and DenoRemoteLockEntry metadata types for deno.lock support
|
||||||
// 16.1.6 - add Dependencies to ElixirMixLockEntry metadata
|
// 16.1.6 - add Dependencies to ElixirMixLockEntry metadata
|
||||||
|
// 16.1.7 - add AppleAppBundleEntry metadata type for the apple app bundle cataloger
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|||||||
@ -9,6 +9,7 @@ func AllTypes() []any {
|
|||||||
return []any{
|
return []any{
|
||||||
pkg.AlpmDBEntry{},
|
pkg.AlpmDBEntry{},
|
||||||
pkg.ApkDBEntry{},
|
pkg.ApkDBEntry{},
|
||||||
|
pkg.AppleAppBundleEntry{},
|
||||||
pkg.BinarySignature{},
|
pkg.BinarySignature{},
|
||||||
pkg.BitnamiSBOMEntry{},
|
pkg.BitnamiSBOMEntry{},
|
||||||
pkg.BunLockEntry{},
|
pkg.BunLockEntry{},
|
||||||
|
|||||||
@ -124,6 +124,7 @@ var jsonTypes = makeJSONTypes(
|
|||||||
jsonNames(pkg.SnapEntry{}, "snap-entry"),
|
jsonNames(pkg.SnapEntry{}, "snap-entry"),
|
||||||
jsonNames(pkg.WordpressPluginEntry{}, "wordpress-plugin-entry", "WordpressMetadata"),
|
jsonNames(pkg.WordpressPluginEntry{}, "wordpress-plugin-entry", "WordpressMetadata"),
|
||||||
jsonNames(pkg.HomebrewFormula{}, "homebrew-formula"),
|
jsonNames(pkg.HomebrewFormula{}, "homebrew-formula"),
|
||||||
|
jsonNames(pkg.AppleAppBundleEntry{}, "apple-app-bundle-entry"),
|
||||||
jsonNames(pkg.LuaRocksPackage{}, "luarocks-package"),
|
jsonNames(pkg.LuaRocksPackage{}, "luarocks-package"),
|
||||||
jsonNames(pkg.TerraformLockProviderEntry{}, "terraform-lock-provider-entry"),
|
jsonNames(pkg.TerraformLockProviderEntry{}, "terraform-lock-provider-entry"),
|
||||||
jsonNames(pkg.DotnetPackagesLockEntry{}, "dotnet-packages-lock-entry"),
|
jsonNames(pkg.DotnetPackagesLockEntry{}, "dotnet-packages-lock-entry"),
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/ai"
|
"github.com/anchore/syft/syft/pkg/cataloger/ai"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/alpine"
|
"github.com/anchore/syft/syft/pkg/cataloger/alpine"
|
||||||
|
"github.com/anchore/syft/syft/pkg/cataloger/apple"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/arch"
|
"github.com/anchore/syft/syft/pkg/cataloger/arch"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/binary"
|
"github.com/anchore/syft/syft/pkg/cataloger/binary"
|
||||||
bitnamiSbomCataloger "github.com/anchore/syft/syft/pkg/cataloger/bitnami"
|
bitnamiSbomCataloger "github.com/anchore/syft/syft/pkg/cataloger/bitnami"
|
||||||
@ -177,6 +178,7 @@ func DefaultPackageTaskFactories() Factories {
|
|||||||
newSimplePackageTaskFactory(wordpress.NewWordpressPluginCataloger, pkgcataloging.DirectoryTag, pkgcataloging.ImageTag, "wordpress"),
|
newSimplePackageTaskFactory(wordpress.NewWordpressPluginCataloger, pkgcataloging.DirectoryTag, pkgcataloging.ImageTag, "wordpress"),
|
||||||
newSimplePackageTaskFactory(terraform.NewLockCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, "terraform"),
|
newSimplePackageTaskFactory(terraform.NewLockCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, "terraform"),
|
||||||
newSimplePackageTaskFactory(homebrew.NewCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "homebrew"),
|
newSimplePackageTaskFactory(homebrew.NewCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "homebrew"),
|
||||||
|
newSimplePackageTaskFactory(apple.NewAppBundleCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "apple"),
|
||||||
newSimplePackageTaskFactory(conda.NewCondaMetaCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.PackageTag, "conda"),
|
newSimplePackageTaskFactory(conda.NewCondaMetaCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.PackageTag, "conda"),
|
||||||
newSimplePackageTaskFactory(snap.NewCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "snap"),
|
newSimplePackageTaskFactory(snap.NewCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "snap"),
|
||||||
newSimplePackageTaskFactory(ai.NewGGUFCataloger, pkgcataloging.DirectoryTag, pkgcataloging.ImageTag, "ai", "model", "gguf", "ml"),
|
newSimplePackageTaskFactory(ai.NewGGUFCataloger, pkgcataloging.DirectoryTag, pkgcataloging.ImageTag, "ai", "model", "gguf", "ml"),
|
||||||
|
|||||||
4422
schema/json/schema-16.1.7.json
Normal file
4422
schema/json/schema-16.1.7.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"$id": "anchore.io/schema/syft/json/16.1.6/document",
|
"$id": "anchore.io/schema/syft/json/16.1.7/document",
|
||||||
"$ref": "#/$defs/Document",
|
"$ref": "#/$defs/Document",
|
||||||
"$defs": {
|
"$defs": {
|
||||||
"AlpmDbEntry": {
|
"AlpmDbEntry": {
|
||||||
@ -249,6 +249,67 @@
|
|||||||
],
|
],
|
||||||
"description": "ApkFileRecord represents a single file listing and metadata from a APK DB entry (which may have many of these file records)."
|
"description": "ApkFileRecord represents a single file listing and metadata from a APK DB entry (which may have many of these file records)."
|
||||||
},
|
},
|
||||||
|
"AppleAppBundleEntry": {
|
||||||
|
"properties": {
|
||||||
|
"bundleIdentifier": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "BundleIdentifier is the unique identifier for the bundle (e.g. \"com.apple.Safari\")"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Name is the short name of the bundle"
|
||||||
|
},
|
||||||
|
"displayName": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "DisplayName is the user-facing name of the bundle"
|
||||||
|
},
|
||||||
|
"executable": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Executable is the name of the executable within the bundle"
|
||||||
|
},
|
||||||
|
"shortVersion": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "ShortVersion is the release (marketing) version of the bundle"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Version is the build version of the bundle, which often differs from the short version"
|
||||||
|
},
|
||||||
|
"packageType": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "PackageType is the four-letter type code (e.g. \"APPL\" for apps, \"FMWK\" for frameworks, \"BNDL\" for bundles)"
|
||||||
|
},
|
||||||
|
"supportedPlatforms": {
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array",
|
||||||
|
"description": "SupportedPlatforms lists the platforms the bundle targets (e.g. \"MacOSX\", \"iPhoneOS\")"
|
||||||
|
},
|
||||||
|
"minimumSystemVersion": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "MinimumSystemVersion is the minimum macOS version required to run the bundle"
|
||||||
|
},
|
||||||
|
"minimumOSVersion": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "MinimumOSVersion is the minimum OS version required for non-macOS platforms (e.g. iOS)"
|
||||||
|
},
|
||||||
|
"copyright": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Copyright is the human-readable copyright notice for the bundle"
|
||||||
|
},
|
||||||
|
"platformName": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "PlatformName is the platform name of the SDK used to build the bundle (e.g. \"macosx\")"
|
||||||
|
},
|
||||||
|
"sdkName": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "SDKName is the name of the SDK used to build the bundle (e.g. \"macosx14.0\")"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
"description": "AppleAppBundleEntry represents metadata about an Apple application bundle (CFBundle) extracted from Info.plist files."
|
||||||
|
},
|
||||||
"BinarySignature": {
|
"BinarySignature": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"matches": {
|
"matches": {
|
||||||
@ -2674,6 +2735,9 @@
|
|||||||
{
|
{
|
||||||
"$ref": "#/$defs/ApkDbEntry"
|
"$ref": "#/$defs/ApkDbEntry"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/$defs/AppleAppBundleEntry"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/$defs/BinarySignature"
|
"$ref": "#/$defs/BinarySignature"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -31,6 +31,7 @@ func Test_OriginatorSupplier(t *testing.T) {
|
|||||||
pkg.GolangModuleEntry{},
|
pkg.GolangModuleEntry{},
|
||||||
pkg.GolangSourceEntry{},
|
pkg.GolangSourceEntry{},
|
||||||
pkg.HomebrewFormula{},
|
pkg.HomebrewFormula{},
|
||||||
|
pkg.AppleAppBundleEntry{},
|
||||||
pkg.HackageStackYamlLockEntry{},
|
pkg.HackageStackYamlLockEntry{},
|
||||||
pkg.HackageStackYamlEntry{},
|
pkg.HackageStackYamlEntry{},
|
||||||
pkg.LinuxKernel{},
|
pkg.LinuxKernel{},
|
||||||
|
|||||||
@ -80,6 +80,8 @@ func SourceInfo(p pkg.Package) string {
|
|||||||
answer = "acquired package info from found wordpress plugin PHP source files"
|
answer = "acquired package info from found wordpress plugin PHP source files"
|
||||||
case pkg.HomebrewPkg:
|
case pkg.HomebrewPkg:
|
||||||
answer = "acquired package info from Homebrew formula"
|
answer = "acquired package info from Homebrew formula"
|
||||||
|
case pkg.AppleAppBundlePkg:
|
||||||
|
answer = "acquired package info from Apple application bundle Info.plist"
|
||||||
case pkg.TerraformPkg:
|
case pkg.TerraformPkg:
|
||||||
answer = "acquired package info from Terraform dependency lock file"
|
answer = "acquired package info from Terraform dependency lock file"
|
||||||
case pkg.ModelPkg:
|
case pkg.ModelPkg:
|
||||||
|
|||||||
@ -343,6 +343,14 @@ func Test_SourceInfo(t *testing.T) {
|
|||||||
"acquired package info from Homebrew formula",
|
"acquired package info from Homebrew formula",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
input: pkg.Package{
|
||||||
|
Type: pkg.AppleAppBundlePkg,
|
||||||
|
},
|
||||||
|
expected: []string{
|
||||||
|
"acquired package info from Apple application bundle Info.plist",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
input: pkg.Package{
|
input: pkg.Package{
|
||||||
Type: pkg.TerraformPkg,
|
Type: pkg.TerraformPkg,
|
||||||
|
|||||||
44
syft/pkg/apple.go
Normal file
44
syft/pkg/apple.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package pkg
|
||||||
|
|
||||||
|
// AppleAppBundleEntry represents metadata about an Apple application bundle (CFBundle) extracted from Info.plist files.
|
||||||
|
// These bundles share the same plist structure across macOS, iOS, watchOS, visionOS, and others.
|
||||||
|
type AppleAppBundleEntry struct {
|
||||||
|
// BundleIdentifier is the unique identifier for the bundle (e.g. "com.apple.Safari")
|
||||||
|
BundleIdentifier string `json:"bundleIdentifier,omitempty"`
|
||||||
|
|
||||||
|
// Name is the short name of the bundle
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
|
||||||
|
// DisplayName is the user-facing name of the bundle
|
||||||
|
DisplayName string `json:"displayName,omitempty"`
|
||||||
|
|
||||||
|
// Executable is the name of the executable within the bundle
|
||||||
|
Executable string `json:"executable,omitempty"`
|
||||||
|
|
||||||
|
// ShortVersion is the release (marketing) version of the bundle
|
||||||
|
ShortVersion string `json:"shortVersion,omitempty"`
|
||||||
|
|
||||||
|
// Version is the build version of the bundle, which often differs from the short version
|
||||||
|
Version string `json:"version,omitempty"`
|
||||||
|
|
||||||
|
// PackageType is the four-letter type code (e.g. "APPL" for apps, "FMWK" for frameworks, "BNDL" for bundles)
|
||||||
|
PackageType string `json:"packageType,omitempty"`
|
||||||
|
|
||||||
|
// SupportedPlatforms lists the platforms the bundle targets (e.g. "MacOSX", "iPhoneOS")
|
||||||
|
SupportedPlatforms []string `json:"supportedPlatforms,omitempty"`
|
||||||
|
|
||||||
|
// MinimumSystemVersion is the minimum macOS version required to run the bundle
|
||||||
|
MinimumSystemVersion string `json:"minimumSystemVersion,omitempty"`
|
||||||
|
|
||||||
|
// MinimumOSVersion is the minimum OS version required for non-macOS platforms (e.g. iOS)
|
||||||
|
MinimumOSVersion string `json:"minimumOSVersion,omitempty"`
|
||||||
|
|
||||||
|
// Copyright is the human-readable copyright notice for the bundle
|
||||||
|
Copyright string `json:"copyright,omitempty"`
|
||||||
|
|
||||||
|
// PlatformName is the platform name of the SDK used to build the bundle (e.g. "macosx")
|
||||||
|
PlatformName string `json:"platformName,omitempty"`
|
||||||
|
|
||||||
|
// SDKName is the name of the SDK used to build the bundle (e.g. "macosx14.0")
|
||||||
|
SDKName string `json:"sdkName,omitempty"`
|
||||||
|
}
|
||||||
42
syft/pkg/cataloger/apple/capabilities.yaml
Normal file
42
syft/pkg/cataloger/apple/capabilities.yaml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Cataloger capabilities. See ../README.md for documentation.
|
||||||
|
|
||||||
|
catalogers:
|
||||||
|
- ecosystem: apple # MANUAL
|
||||||
|
name: apple-app-bundle-cataloger # AUTO-GENERATED
|
||||||
|
type: generic # AUTO-GENERATED
|
||||||
|
source: # AUTO-GENERATED
|
||||||
|
file: syft/pkg/cataloger/apple/cataloger.go
|
||||||
|
function: NewAppBundleCataloger
|
||||||
|
selectors: # AUTO-GENERATED
|
||||||
|
- apple
|
||||||
|
- directory
|
||||||
|
- image
|
||||||
|
- installed
|
||||||
|
- package
|
||||||
|
parsers: # AUTO-GENERATED structure
|
||||||
|
- function: parseInfoPlist
|
||||||
|
detector: # AUTO-GENERATED
|
||||||
|
method: glob # AUTO-GENERATED
|
||||||
|
criteria: # AUTO-GENERATED
|
||||||
|
- '**/*.app/Contents/Info.plist'
|
||||||
|
metadata_types: # AUTO-GENERATED
|
||||||
|
- pkg.AppleAppBundleEntry
|
||||||
|
package_types: # AUTO-GENERATED
|
||||||
|
- apple-app-bundle
|
||||||
|
json_schema_types: # AUTO-GENERATED
|
||||||
|
- AppleAppBundleEntry
|
||||||
|
capabilities: # MANUAL - preserved across regeneration
|
||||||
|
- name: license
|
||||||
|
default: false
|
||||||
|
- name: dependency.depth
|
||||||
|
default: []
|
||||||
|
- name: dependency.edges
|
||||||
|
default: ""
|
||||||
|
- name: dependency.kinds
|
||||||
|
default: []
|
||||||
|
- name: package_manager.files.listing
|
||||||
|
default: false
|
||||||
|
- name: package_manager.files.digests
|
||||||
|
default: false
|
||||||
|
- name: package_manager.package_integrity_hash
|
||||||
|
default: false
|
||||||
12
syft/pkg/cataloger/apple/cataloger.go
Normal file
12
syft/pkg/cataloger/apple/cataloger.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package apple
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/pkg/cataloger/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewAppBundleCataloger returns a cataloger for Apple application bundles (.app), reading their Info.plist (CFBundle).
|
||||||
|
func NewAppBundleCataloger() pkg.Cataloger {
|
||||||
|
return generic.NewCataloger("apple-app-bundle-cataloger").
|
||||||
|
WithParserByGlobs(parseInfoPlist, "**/*.app/Contents/Info.plist")
|
||||||
|
}
|
||||||
180
syft/pkg/cataloger/apple/cataloger_test.go
Normal file
180
syft/pkg/cataloger/apple/cataloger_test.go
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
package apple
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/artifact"
|
||||||
|
"github.com/anchore/syft/syft/file"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_AppleAppBundleCataloger_Globs(t *testing.T) {
|
||||||
|
pkgtest.NewCatalogTester().
|
||||||
|
FromDirectory(t, "testdata/install-example").
|
||||||
|
ExpectsResolverContentQueries([]string{
|
||||||
|
"Applications/Slack.app/Contents/Info.plist",
|
||||||
|
}).
|
||||||
|
TestCataloger(t, NewAppBundleCataloger())
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_AppleAppBundleCataloger(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fixture string
|
||||||
|
expected []pkg.Package
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "xml plist (Slack)",
|
||||||
|
fixture: "testdata/install-example",
|
||||||
|
expected: []pkg.Package{
|
||||||
|
{
|
||||||
|
Name: "Slack",
|
||||||
|
Version: "4.50.128",
|
||||||
|
Type: pkg.AppleAppBundlePkg,
|
||||||
|
FoundBy: "apple-app-bundle-cataloger",
|
||||||
|
Locations: file.NewLocationSet(
|
||||||
|
file.NewLocation("Applications/Slack.app/Contents/Info.plist").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
|
||||||
|
),
|
||||||
|
PURL: "", // no standard purl type for apple app bundles
|
||||||
|
Metadata: pkg.AppleAppBundleEntry{
|
||||||
|
BundleIdentifier: "com.tinyspeck.slackmacgap",
|
||||||
|
Name: "Slack",
|
||||||
|
DisplayName: "Slack",
|
||||||
|
Executable: "Slack",
|
||||||
|
ShortVersion: "4.50.128",
|
||||||
|
Version: "450000128",
|
||||||
|
PackageType: "APPL",
|
||||||
|
MinimumSystemVersion: "12.0",
|
||||||
|
Copyright: "©2026 Slack Technologies LLC, a Salesforce company. All rights reserved.",
|
||||||
|
SDKName: "macosx15.5",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// platform/array fields; values are from a real Ghostty.app
|
||||||
|
name: "platform fields (Ghostty)",
|
||||||
|
fixture: "testdata/native-app-example",
|
||||||
|
expected: []pkg.Package{
|
||||||
|
{
|
||||||
|
Name: "Ghostty",
|
||||||
|
Version: "1.3.1",
|
||||||
|
Type: pkg.AppleAppBundlePkg,
|
||||||
|
FoundBy: "apple-app-bundle-cataloger",
|
||||||
|
Locations: file.NewLocationSet(
|
||||||
|
file.NewLocation("Applications/Ghostty.app/Contents/Info.plist").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
|
||||||
|
),
|
||||||
|
PURL: "",
|
||||||
|
Metadata: pkg.AppleAppBundleEntry{
|
||||||
|
BundleIdentifier: "com.mitchellh.ghostty",
|
||||||
|
Name: "Ghostty",
|
||||||
|
DisplayName: "Ghostty",
|
||||||
|
Executable: "ghostty",
|
||||||
|
ShortVersion: "1.3.1",
|
||||||
|
Version: "15212",
|
||||||
|
PackageType: "APPL",
|
||||||
|
SupportedPlatforms: []string{"MacOSX"},
|
||||||
|
MinimumSystemVersion: "13.0",
|
||||||
|
PlatformName: "macosx",
|
||||||
|
SDKName: "macosx26.2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
pkgtest.NewCatalogTester().
|
||||||
|
FromDirectory(t, tt.fixture).
|
||||||
|
Expects(tt.expected, nil).
|
||||||
|
TestCataloger(t, NewAppBundleCataloger())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_parseInfoPlist(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fixture string
|
||||||
|
wantName string
|
||||||
|
wantVersion string
|
||||||
|
wantBundleID string
|
||||||
|
wantNoPackage bool
|
||||||
|
wantParseErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "name falls back to executable",
|
||||||
|
fixture: "testdata/parse-cases/name-from-executable.plist",
|
||||||
|
wantName: "Exec",
|
||||||
|
wantVersion: "1.0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "name falls back to bundle identifier",
|
||||||
|
fixture: "testdata/parse-cases/name-from-identifier.plist",
|
||||||
|
wantName: "com.example.app",
|
||||||
|
wantVersion: "1.0",
|
||||||
|
wantBundleID: "com.example.app",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "version falls back to bundle version",
|
||||||
|
fixture: "testdata/parse-cases/version-from-bundle-version.plist",
|
||||||
|
wantName: "Name",
|
||||||
|
wantVersion: "42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no package without a name",
|
||||||
|
fixture: "testdata/parse-cases/no-name.plist",
|
||||||
|
wantNoPackage: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no package without a version",
|
||||||
|
fixture: "testdata/parse-cases/no-version.plist",
|
||||||
|
wantNoPackage: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "malformed plist returns an error",
|
||||||
|
fixture: "testdata/parse-cases/malformed.plist",
|
||||||
|
wantParseErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
pkgs, _, err := parseFixture(t, tt.fixture)
|
||||||
|
if tt.wantParseErr {
|
||||||
|
require.Error(t, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if tt.wantNoPackage {
|
||||||
|
assert.Empty(t, pkgs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
require.Len(t, pkgs, 1)
|
||||||
|
assert.Equal(t, tt.wantName, pkgs[0].Name)
|
||||||
|
assert.Equal(t, tt.wantVersion, pkgs[0].Version)
|
||||||
|
assert.Equal(t, pkg.AppleAppBundlePkg, pkgs[0].Type)
|
||||||
|
assert.Empty(t, pkgs[0].PURL)
|
||||||
|
meta, ok := pkgs[0].Metadata.(pkg.AppleAppBundleEntry)
|
||||||
|
require.True(t, ok)
|
||||||
|
assert.Equal(t, tt.wantBundleID, meta.BundleIdentifier)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseFixture(t *testing.T, path string) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
|
t.Helper()
|
||||||
|
f, err := os.Open(path)
|
||||||
|
require.NoError(t, err)
|
||||||
|
t.Cleanup(func() { _ = f.Close() })
|
||||||
|
return parseInfoPlist(context.Background(), nil, nil, file.NewLocationReadCloser(file.NewLocation(path), f))
|
||||||
|
}
|
||||||
20
syft/pkg/cataloger/apple/package.go
Normal file
20
syft/pkg/cataloger/apple/package.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package apple
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/anchore/syft/syft/file"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newAppBundlePackage(name, version string, metadata pkg.AppleAppBundleEntry, location file.Location) pkg.Package {
|
||||||
|
p := pkg.Package{
|
||||||
|
Name: name,
|
||||||
|
Version: version,
|
||||||
|
Type: pkg.AppleAppBundlePkg,
|
||||||
|
// note: there is no standard purl type for Apple app bundles, so we intentionally leave the PURL empty.
|
||||||
|
Locations: file.NewLocationSet(location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)),
|
||||||
|
Metadata: metadata,
|
||||||
|
}
|
||||||
|
|
||||||
|
p.SetID()
|
||||||
|
return p
|
||||||
|
}
|
||||||
91
syft/pkg/cataloger/apple/parse_info_plist.go
Normal file
91
syft/pkg/cataloger/apple/parse_info_plist.go
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package apple
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"howett.net/plist"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/artifact"
|
||||||
|
"github.com/anchore/syft/syft/file"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/pkg/cataloger/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// infoPlist captures the raw CFBundle keys read from an Info.plist. It is kept separate from the public
|
||||||
|
// pkg.AppleAppBundleEntry so the parser can read fields without committing to expressing all of them.
|
||||||
|
type infoPlist struct {
|
||||||
|
CFBundleIdentifier string `plist:"CFBundleIdentifier"`
|
||||||
|
CFBundleName string `plist:"CFBundleName"`
|
||||||
|
CFBundleDisplayName string `plist:"CFBundleDisplayName"`
|
||||||
|
CFBundleExecutable string `plist:"CFBundleExecutable"`
|
||||||
|
CFBundleShortVersionString string `plist:"CFBundleShortVersionString"`
|
||||||
|
CFBundleVersion string `plist:"CFBundleVersion"`
|
||||||
|
CFBundlePackageType string `plist:"CFBundlePackageType"`
|
||||||
|
CFBundleSupportedPlatforms []string `plist:"CFBundleSupportedPlatforms"`
|
||||||
|
LSMinimumSystemVersion string `plist:"LSMinimumSystemVersion"`
|
||||||
|
MinimumOSVersion string `plist:"MinimumOSVersion"`
|
||||||
|
NSHumanReadableCopyright string `plist:"NSHumanReadableCopyright"`
|
||||||
|
DTPlatformName string `plist:"DTPlatformName"`
|
||||||
|
DTSDKName string `plist:"DTSDKName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInfoPlist(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
|
// 5MB cap matches the convention in syft/linux; Info.plist files are far smaller
|
||||||
|
data, err := io.ReadAll(io.LimitReader(reader, 5*1024*1024))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("unable to read file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var info infoPlist
|
||||||
|
if _, err := plist.Unmarshal(data, &info); err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("unable to parse plist: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
name := info.CFBundleDisplayName
|
||||||
|
if name == "" {
|
||||||
|
name = info.CFBundleName
|
||||||
|
}
|
||||||
|
if name == "" {
|
||||||
|
name = info.CFBundleExecutable
|
||||||
|
}
|
||||||
|
if name == "" {
|
||||||
|
// last-resort name so identifiable bundles aren't dropped (e.g. com.apple.Safari)
|
||||||
|
name = info.CFBundleIdentifier
|
||||||
|
}
|
||||||
|
|
||||||
|
version := info.CFBundleShortVersionString
|
||||||
|
if version == "" {
|
||||||
|
version = info.CFBundleVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
if name == "" || version == "" {
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgs := []pkg.Package{
|
||||||
|
newAppBundlePackage(name, version, info.toEntry(), reader.Location),
|
||||||
|
}
|
||||||
|
|
||||||
|
return pkgs, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toEntry maps the parsed plist into the public metadata type.
|
||||||
|
func (i infoPlist) toEntry() pkg.AppleAppBundleEntry {
|
||||||
|
return pkg.AppleAppBundleEntry{
|
||||||
|
BundleIdentifier: i.CFBundleIdentifier,
|
||||||
|
Name: i.CFBundleName,
|
||||||
|
DisplayName: i.CFBundleDisplayName,
|
||||||
|
Executable: i.CFBundleExecutable,
|
||||||
|
ShortVersion: i.CFBundleShortVersionString,
|
||||||
|
Version: i.CFBundleVersion,
|
||||||
|
PackageType: i.CFBundlePackageType,
|
||||||
|
SupportedPlatforms: i.CFBundleSupportedPlatforms,
|
||||||
|
MinimumSystemVersion: i.LSMinimumSystemVersion,
|
||||||
|
MinimumOSVersion: i.MinimumOSVersion,
|
||||||
|
Copyright: i.NSHumanReadableCopyright,
|
||||||
|
PlatformName: i.DTPlatformName,
|
||||||
|
SDKName: i.DTSDKName,
|
||||||
|
}
|
||||||
|
}
|
||||||
26
syft/pkg/cataloger/apple/testdata/install-example/Applications/Slack.app/Contents/Info.plist
vendored
Normal file
26
syft/pkg/cataloger/apple/testdata/install-example/Applications/Slack.app/Contents/Info.plist
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>Slack</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>Slack</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>Slack</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.tinyspeck.slackmacgap</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>4.50.128</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>450000128</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>12.0</string>
|
||||||
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
<string>©2026 Slack Technologies LLC, a Salesforce company. All rights reserved.</string>
|
||||||
|
<key>DTSDKName</key>
|
||||||
|
<string>macosx15.5</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>Ghostty</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>Ghostty</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>ghostty</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.mitchellh.ghostty</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.3.1</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>15212</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleSupportedPlatforms</key>
|
||||||
|
<array>
|
||||||
|
<string>MacOSX</string>
|
||||||
|
</array>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>13.0</string>
|
||||||
|
<key>DTPlatformName</key>
|
||||||
|
<string>macosx</string>
|
||||||
|
<key>DTSDKName</key>
|
||||||
|
<string>macosx26.2</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
1
syft/pkg/cataloger/apple/testdata/parse-cases/malformed.plist
vendored
Normal file
1
syft/pkg/cataloger/apple/testdata/parse-cases/malformed.plist
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
this is not a valid plist
|
||||||
10
syft/pkg/cataloger/apple/testdata/parse-cases/name-from-executable.plist
vendored
Normal file
10
syft/pkg/cataloger/apple/testdata/parse-cases/name-from-executable.plist
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>Exec</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
10
syft/pkg/cataloger/apple/testdata/parse-cases/name-from-identifier.plist
vendored
Normal file
10
syft/pkg/cataloger/apple/testdata/parse-cases/name-from-identifier.plist
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.example.app</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
8
syft/pkg/cataloger/apple/testdata/parse-cases/no-name.plist
vendored
Normal file
8
syft/pkg/cataloger/apple/testdata/parse-cases/no-name.plist
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
8
syft/pkg/cataloger/apple/testdata/parse-cases/no-version.plist
vendored
Normal file
8
syft/pkg/cataloger/apple/testdata/parse-cases/no-version.plist
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>Name</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
10
syft/pkg/cataloger/apple/testdata/parse-cases/version-from-bundle-version.plist
vendored
Normal file
10
syft/pkg/cataloger/apple/testdata/parse-cases/version-from-bundle-version.plist
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>Name</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>42</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@ -54,6 +54,7 @@ const (
|
|||||||
TerraformPkg Type = "terraform"
|
TerraformPkg Type = "terraform"
|
||||||
WordpressPluginPkg Type = "wordpress-plugin"
|
WordpressPluginPkg Type = "wordpress-plugin"
|
||||||
HomebrewPkg Type = "homebrew"
|
HomebrewPkg Type = "homebrew"
|
||||||
|
AppleAppBundlePkg Type = "apple-app-bundle"
|
||||||
ModelPkg Type = "model"
|
ModelPkg Type = "model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -99,6 +100,7 @@ var AllPkgs = []Type{
|
|||||||
TerraformPkg,
|
TerraformPkg,
|
||||||
WordpressPluginPkg,
|
WordpressPluginPkg,
|
||||||
HomebrewPkg,
|
HomebrewPkg,
|
||||||
|
AppleAppBundlePkg,
|
||||||
ModelPkg,
|
ModelPkg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -161,6 +161,7 @@ func TestTypeFromPURL(t *testing.T) {
|
|||||||
expectedTypes.Remove(string(TerraformPkg))
|
expectedTypes.Remove(string(TerraformPkg))
|
||||||
expectedTypes.Remove(string(GraalVMNativeImagePkg))
|
expectedTypes.Remove(string(GraalVMNativeImagePkg))
|
||||||
expectedTypes.Remove(string(ModelPkg)) // no valid purl for ai artifacts currently
|
expectedTypes.Remove(string(ModelPkg)) // no valid purl for ai artifacts currently
|
||||||
|
expectedTypes.Remove(string(AppleAppBundlePkg)) // no standard purl type for apple app bundles
|
||||||
expectedTypes.Remove(string(PhpPeclPkg)) // we should always consider this a pear package
|
expectedTypes.Remove(string(PhpPeclPkg)) // we should always consider this a pear package
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user