mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-21 14:50:53 -08:00
feat(swift): add vulns for cocoapods (#5037)
* add vulns for cocoapods, fix purl * update docs * remove go-dep-parser replace * update purl and test * bump github.com/DmitriyLewen/trivy-db * remove replace for trivy-db * remove added sbom tests * add test for Package() func * add wrong epoch test * refactor docs * add comment to join the module and submodule in purl * docs: add an example --------- Co-authored-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
@@ -17,7 +17,7 @@ If the target is a pre-build project, like a code repository, Trivy will analyze
|
||||
On the other hand, when the target is a post-build artifact, like a container image, Trivy will analyze installed package metadata like `.gemspec`, binary files, and so on.
|
||||
|
||||
| Language | File | Image[^5] | Rootfs[^6] | Filesystem[^7] | Repository[^8] |
|
||||
| -------------------- | ------------------------------------------------------------------------------------------ | :-------: | :--------: | :------------: | :------------: |
|
||||
|----------------------|--------------------------------------------------------------------------------------------|:---------:|:----------:|:--------------:|:--------------:|
|
||||
| [Ruby](ruby.md) | Gemfile.lock | - | - | ✅ | ✅ |
|
||||
| | gemspec | ✅ | ✅ | - | - |
|
||||
| [Python](python.md) | Pipfile.lock | - | - | ✅ | ✅ |
|
||||
@@ -45,6 +45,7 @@ On the other hand, when the target is a post-build artifact, like a container im
|
||||
| [Elixir](elixir.md) | mix.lock[^10] | - | - | ✅ | ✅ |
|
||||
| [Dart](dart.md) | pubspec.lock | - | - | ✅ | ✅ |
|
||||
| [Swift](swift.md) | Podfile.lock | - | - | ✅ | ✅ |
|
||||
| | Package.resolved | - | - | ✅ | ✅ |
|
||||
|
||||
The path of these files does not matter.
|
||||
|
||||
|
||||
@@ -1,10 +1,44 @@
|
||||
# Swift
|
||||
|
||||
Trivy supports [CocoaPods][cocoapods] for Swift packages.
|
||||
Trivy supports [CocoaPods][cocoapods] and [Swift][swift] package managers.
|
||||
|
||||
The following scanners are supported.
|
||||
|
||||
| Package manager | SBOM | Vulnerability | License |
|
||||
| --------------- | :---: | :-----------: | :-----: |
|
||||
| CocoaPods | ✓ | - | - |
|
||||
| Package manager | SBOM | Vulnerability | License |
|
||||
|-----------------|:----:|:-------------:|:-------:|
|
||||
| Swift | ✓ | ✓ | - |
|
||||
| CocoaPods | ✓ | ✓ | - |
|
||||
|
||||
[cocoapods]: https://cocoapods.org/
|
||||
The following table provides an outline of the features Trivy offers.
|
||||
|
||||
| Package manager | File | Transitive dependencies | Dev dependencies | [Dependency graph][dependency-graph] | Position |
|
||||
|:---------------:|------------------|:-----------------------:|:----------------:|:------------------------------------:|:--------:|
|
||||
| Swift | Package.resolved | ✓ | Included | - | ✓ |
|
||||
| CocoaPods | Podfile.lock | ✓ | Included | ✓ | - |
|
||||
|
||||
These may be enabled or disabled depending on the target.
|
||||
See [here](./index.md) for the detail.
|
||||
|
||||
## Swift
|
||||
Trivy parses [Package.resolved][package-resolved] file to find dependencies.
|
||||
Don't forget to update (`swift package update` command) this file before scanning.
|
||||
|
||||
## CocoaPods
|
||||
CocoaPods uses package names in `PodFile.lock`, but [GitHub Advisory Database (GHSA)][ghsa] Trivy relies on uses Git URLs.
|
||||
We parse [the CocoaPods Specs][cocoapods-specs] to match package names and links.
|
||||
|
||||
!!! note "Limitation"
|
||||
Since [GHSA][ghsa] holds only Git URLs, such as github.com/apple/swift-nio,
|
||||
Trivy can't identify affected submodules, and detect all submodules maintained by the same URL.
|
||||
For example, [SwiftNIOHTTP1][niohttp1] and [SwiftNIOWebSocket][niowebsocket] both are maintained under `github.com/apple/swift-nio`,
|
||||
and Trivy detect CVE-2022-3215 for both of them, even though only [SwiftNIOHTTP1][niohttp1] is actually affected.
|
||||
|
||||
[cocoapods]: https://cocoapods.org/
|
||||
[cocoapods-specs]: https://github.com/CocoaPods/Specs
|
||||
[ghsa]: https://github.com/advisories?query=type%3Areviewed+ecosystem%3Aswift
|
||||
[swift]: https://www.swift.org/package-manager/
|
||||
[package-resolved]: https://github.com/apple/swift-package-manager/blob/4a42f2519e3f7b8a731c5ed89b47ed577df8f86c/Documentation/Usage.md#resolving-versions-packageresolved-file
|
||||
[dependency-graph]: ../../configuration/reporting.md#show-origins-of-vulnerable-dependencies
|
||||
|
||||
[niohttp1]: https://cocoapods.org/pods/SwiftNIOHTTP1
|
||||
[niowebsocket]: https://cocoapods.org/pods/SwiftNIOWebSocket
|
||||
@@ -77,7 +77,7 @@ See [here](../coverage/language/index.md#supported-languages) for the supported
|
||||
### Data Sources
|
||||
|
||||
| Language | Source | Commercial Use | Delay[^1] |
|
||||
| -------- | --------------------------------------------------- | :------------: | :-------: |
|
||||
|----------|-----------------------------------------------------|:--------------:|:---------:|
|
||||
| PHP | [PHP Security Advisories Database][php] | ✅ | - |
|
||||
| | [GitHub Advisory Database (Composer)][php-ghsa] | ✅ | - |
|
||||
| Python | [GitHub Advisory Database (pip)][python-ghsa] | ✅ | - |
|
||||
@@ -93,7 +93,8 @@ See [here](../coverage/language/index.md#supported-languages) for the supported
|
||||
| .NET | [GitHub Advisory Database (NuGet)][dotnet-ghsa] | ✅ | - |
|
||||
| C/C++ | [GitLab Advisories Community][gitlab] | ✅ | 1 month |
|
||||
| Dart | [GitHub Advisory Database (Pub)][pub-ghsa] | ✅ | - |
|
||||
| Elixir | [GitHub Advisory Database (Erlang)][erlang-ghsa] | ✅ | |
|
||||
| Elixir | [GitHub Advisory Database (Erlang)][erlang-ghsa] | ✅ | - |
|
||||
| Swift | [GitHub Advisory Database (Swift)][swift-ghsa] | ✅ | - |
|
||||
|
||||
[^1]: Intentional delay between vulnerability disclosure and registration in the DB
|
||||
|
||||
@@ -168,6 +169,7 @@ Currently, specifying a username and password is not supported.
|
||||
[pub-ghsa]: https://github.com/advisories?query=ecosystem%3Apub
|
||||
[erlang-ghsa]: https://github.com/advisories?query=ecosystem%3Aerlang
|
||||
[go-ghsa]: https://github.com/advisories?query=ecosystem%3Ago
|
||||
[swift-ghsa]: https://github.com/advisories?query=ecosystem%3Aswift
|
||||
|
||||
[php]: https://github.com/FriendsOfPHP/security-advisories
|
||||
[ruby]: https://github.com/rubysec/ruby-advisory-db
|
||||
|
||||
4
go.mod
4
go.mod
@@ -14,7 +14,7 @@ require (
|
||||
github.com/alicebob/miniredis/v2 v2.30.4
|
||||
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986
|
||||
github.com/aquasecurity/defsec v0.91.1
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20230823094455-40c1f85cc942
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20230825043456-df72a286b673
|
||||
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce
|
||||
github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798
|
||||
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46
|
||||
@@ -23,7 +23,7 @@ require (
|
||||
github.com/aquasecurity/table v1.8.0
|
||||
github.com/aquasecurity/testdocker v0.0.0-20230111101738-e741bda259da
|
||||
github.com/aquasecurity/tml v0.6.1
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230823084507-315928e846ff
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230828105148-2c9c4da5a321
|
||||
github.com/aquasecurity/trivy-java-db v0.0.0-20230209231723-7cddb1406728
|
||||
github.com/aquasecurity/trivy-kubernetes v0.5.7-0.20230828123538-ef13fef6ce5b
|
||||
github.com/aws/aws-sdk-go v1.44.273
|
||||
|
||||
8
go.sum
8
go.sum
@@ -325,8 +325,8 @@ github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 h1:2a30
|
||||
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986/go.mod h1:NT+jyeCzXk6vXR5MTkdn4z64TgGfE5HMLC8qfj5unl8=
|
||||
github.com/aquasecurity/defsec v0.91.1 h1:dBIPm6Tva9I+ZTQv+6t9wob3ZlMSu8NFqMJr4mgJC5A=
|
||||
github.com/aquasecurity/defsec v0.91.1/go.mod h1:l/srzxtuuyb6c6FlqUvMp3xw2ZbvuZ0l9972MNJM7V8=
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20230823094455-40c1f85cc942 h1:VGfeUtZyya9Vsl8enDurZ7pb/NDp2aJlL2rx2g4pR6A=
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20230823094455-40c1f85cc942/go.mod h1:0+GvQF0gL4YEAAUPpNeLeGpFDxMvvIHLMd7vk9bpwko=
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20230825043456-df72a286b673 h1:RMhUzr2ZfQ8OAO26aUkqbwfxK7d3ieFtPqUhiwTxOe0=
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20230825043456-df72a286b673/go.mod h1:0+GvQF0gL4YEAAUPpNeLeGpFDxMvvIHLMd7vk9bpwko=
|
||||
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce h1:QgBRgJvtEOBtUXilDb1MLi1p1MWoyFDXAu5DEUl5nwM=
|
||||
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce/go.mod h1:HXgVzOPvXhVGLJs4ZKO817idqr/xhwsTcj17CLYY74s=
|
||||
github.com/aquasecurity/go-mock-aws v0.0.0-20230328195059-5bf52338aec3 h1:Vt9y1gZS5JGY3tsL9zc++Cg4ofX51CG7PaMyC5SXWPg=
|
||||
@@ -345,8 +345,8 @@ github.com/aquasecurity/testdocker v0.0.0-20230111101738-e741bda259da h1:pj/adfN
|
||||
github.com/aquasecurity/testdocker v0.0.0-20230111101738-e741bda259da/go.mod h1:852lbQLpK2nCwlR4ZLYIccxYCfoQao6q9Nl6tjz54v8=
|
||||
github.com/aquasecurity/tml v0.6.1 h1:y2ZlGSfrhnn7t4ZJ/0rotuH+v5Jgv6BDDO5jB6A9gwo=
|
||||
github.com/aquasecurity/tml v0.6.1/go.mod h1:OnYMWY5lvI9ejU7yH9LCberWaaTBW7hBFsITiIMY2yY=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230823084507-315928e846ff h1:+MLnPm81Msu921N/lBrKd/NwwBrrzRoTgyMq0pIUhbs=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230823084507-315928e846ff/go.mod h1:iJSGMMclPEhkYeyiN9i+gzjV9jhEv+XfPzfVgFhfvTE=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230828105148-2c9c4da5a321 h1:oAXkM8x6jMal+6p2XB78+ntPs5LGjxZhtWHdOy4crlg=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230828105148-2c9c4da5a321/go.mod h1:WJ5Qnk5ZNGWvks07GOZe2IOsuXrPfSC5c8hYGOGfrsU=
|
||||
github.com/aquasecurity/trivy-java-db v0.0.0-20230209231723-7cddb1406728 h1:0eS+V7SXHgqoT99tV1mtMW6HL4HdoB9qGLMCb1fZp8A=
|
||||
github.com/aquasecurity/trivy-java-db v0.0.0-20230209231723-7cddb1406728/go.mod h1:Ldya37FLi0e/5Cjq2T5Bty7cFkzUDwTcPeQua+2M8i8=
|
||||
github.com/aquasecurity/trivy-kubernetes v0.5.7-0.20230828123538-ef13fef6ce5b h1:0COfg0HtJm6uKJn/mMBQUgrVmrIxcktlDPR35LracKI=
|
||||
|
||||
69
integration/testdata/cocoapods.json.golden
vendored
69
integration/testdata/cocoapods.json.golden
vendored
@@ -21,44 +21,39 @@
|
||||
"Type": "cocoapods",
|
||||
"Packages": [
|
||||
{
|
||||
"ID": "AppCenter/4.2.0",
|
||||
"Name": "AppCenter",
|
||||
"Version": "4.2.0",
|
||||
"DependsOn": [
|
||||
"AppCenter/Analytics/4.2.0",
|
||||
"AppCenter/Crashes/4.2.0"
|
||||
"ID": "_NIODataStructures@2.41.0",
|
||||
"Name": "_NIODataStructures",
|
||||
"Version": "2.41.0",
|
||||
"Layer": {}
|
||||
}
|
||||
],
|
||||
"Vulnerabilities": [
|
||||
{
|
||||
"VulnerabilityID": "CVE-2022-3215",
|
||||
"PkgID": "_NIODataStructures@2.41.0",
|
||||
"PkgName": "_NIODataStructures",
|
||||
"InstalledVersion": "2.41.0",
|
||||
"FixedVersion": "2.29.1, 2.39.1, 2.42.0",
|
||||
"Status": "fixed",
|
||||
"Layer": {},
|
||||
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2022-3215",
|
||||
"Title": "SwiftNIO vulnerable to Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Response Splitting')",
|
||||
"Description": "`NIOHTTP1` and projects using it for generating HTTP responses, including SwiftNIO, can be subject to a HTTP Response Injection attack...",
|
||||
"Severity": "MEDIUM",
|
||||
"CVSS": {
|
||||
"ghsa": {
|
||||
"V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
|
||||
"V3Score": 5.3
|
||||
}
|
||||
},
|
||||
"References": [
|
||||
"https://github.com/apple/swift-nio/security/advisories/GHSA-7fj7-39wj-c64f",
|
||||
"https://nvd.nist.gov/vuln/detail/CVE-2022-3215",
|
||||
"https://github.com/apple/swift-nio/commit/a16e2f54a25b2af217044e5168997009a505930f",
|
||||
"https://github.com/advisories/GHSA-7fj7-39wj-c64f"
|
||||
],
|
||||
"Layer": {}
|
||||
},
|
||||
{
|
||||
"ID": "AppCenter/Analytics/4.2.0",
|
||||
"Name": "AppCenter/Analytics",
|
||||
"Version": "4.2.0",
|
||||
"DependsOn": [
|
||||
"AppCenter/Core/4.2.0"
|
||||
],
|
||||
"Layer": {}
|
||||
},
|
||||
{
|
||||
"ID": "AppCenter/Core/4.2.0",
|
||||
"Name": "AppCenter/Core",
|
||||
"Version": "4.2.0",
|
||||
"Layer": {}
|
||||
},
|
||||
{
|
||||
"ID": "AppCenter/Crashes/4.2.0",
|
||||
"Name": "AppCenter/Crashes",
|
||||
"Version": "4.2.0",
|
||||
"DependsOn": [
|
||||
"AppCenter/Core/4.2.0"
|
||||
],
|
||||
"Layer": {}
|
||||
},
|
||||
{
|
||||
"ID": "KeychainAccess/4.2.1",
|
||||
"Name": "KeychainAccess",
|
||||
"Version": "4.2.1",
|
||||
"Layer": {}
|
||||
"PublishedDate": "2023-06-07T16:01:53Z",
|
||||
"LastModifiedDate": "2023-06-19T16:45:07Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
14
integration/testdata/fixtures/db/cocoapods.yaml
vendored
Normal file
14
integration/testdata/fixtures/db/cocoapods.yaml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
- bucket: "cocoapods::GitHub Security Advisory Cocoapods"
|
||||
pairs:
|
||||
- bucket: _NIODataStructures
|
||||
pairs:
|
||||
- key: CVE-2022-3215
|
||||
value:
|
||||
PatchedVersions:
|
||||
- "2.29.1"
|
||||
- "2.39.1"
|
||||
- "2.42.0"
|
||||
VulnerableVersions:
|
||||
- "< 2.29.1"
|
||||
- ">= 2.39.0, < 2.39.1"
|
||||
- ">= 2.41.0, < 2.42.0"
|
||||
@@ -1,12 +1,16 @@
|
||||
PODS:
|
||||
- AppCenter (4.2.0):
|
||||
- AppCenter/Analytics (= 4.2.0)
|
||||
- AppCenter/Crashes (= 4.2.0)
|
||||
- AppCenter/Analytics (4.2.0):
|
||||
- AppCenter/Core
|
||||
- AppCenter/Core (4.2.0)
|
||||
- AppCenter/Crashes (4.2.0):
|
||||
- AppCenter/Core
|
||||
- KeychainAccess (4.2.1)
|
||||
- _NIODataStructures (2.41.0)
|
||||
|
||||
COCOAPODS: 1.11.2
|
||||
DEPENDENCIES:
|
||||
- _NIODataStructures (= 2.41.0)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- _NIODataStructures
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
_NIODataStructures: 3d45d8e70a1d17a15b1dc59d102c63dbc0525ffd
|
||||
|
||||
PODFILE CHECKSUM: 2acff18c7f9246879b6a1a2d04e5decbc9410ef4
|
||||
|
||||
COCOAPODS: 1.12.1
|
||||
@@ -66,8 +66,10 @@ func NewDriver(libType string) (Driver, bool) {
|
||||
ecosystem = vulnerability.Swift
|
||||
comparer = compare.GenericComparer{}
|
||||
case ftypes.Cocoapods:
|
||||
log.Logger.Warn("CocoaPods is supported for SBOM, not for vulnerability scanning")
|
||||
return Driver{}, false
|
||||
// CocoaPods uses RubyGems version specifiers
|
||||
// https://guides.cocoapods.org/making/making-a-cocoapod.html#cocoapods-versioning-specifics
|
||||
ecosystem = vulnerability.Cocoapods
|
||||
comparer = rubygems.Comparer{}
|
||||
case ftypes.CondaPkg:
|
||||
log.Logger.Warn("Conda package is supported for SBOM, not for vulnerability scanning")
|
||||
return Driver{}, false
|
||||
|
||||
@@ -181,6 +181,7 @@ var (
|
||||
TypeRustBinary,
|
||||
TypeConanLock,
|
||||
TypeCocoaPods,
|
||||
TypeSwift,
|
||||
TypePubSpecLock,
|
||||
TypeMixLock,
|
||||
}
|
||||
@@ -199,6 +200,7 @@ var (
|
||||
TypeConanLock,
|
||||
TypeGradleLock,
|
||||
TypeCocoaPods,
|
||||
TypeSwift,
|
||||
TypePubSpecLock,
|
||||
TypeMixLock,
|
||||
}
|
||||
|
||||
@@ -27,37 +27,37 @@ func Test_cocoaPodsLockAnalyzer_Analyze(t *testing.T) {
|
||||
FilePath: "testdata/happy.lock",
|
||||
Libraries: types.Packages{
|
||||
{
|
||||
ID: "AppCenter/4.2.0",
|
||||
ID: "AppCenter@4.2.0",
|
||||
Name: "AppCenter",
|
||||
Version: "4.2.0",
|
||||
DependsOn: []string{
|
||||
"AppCenter/Analytics/4.2.0",
|
||||
"AppCenter/Crashes/4.2.0",
|
||||
"AppCenter/Analytics@4.2.0",
|
||||
"AppCenter/Crashes@4.2.0",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "AppCenter/Analytics/4.2.0",
|
||||
ID: "AppCenter/Analytics@4.2.0",
|
||||
Name: "AppCenter/Analytics",
|
||||
Version: "4.2.0",
|
||||
DependsOn: []string{
|
||||
"AppCenter/Core/4.2.0",
|
||||
"AppCenter/Core@4.2.0",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "AppCenter/Core/4.2.0",
|
||||
ID: "AppCenter/Core@4.2.0",
|
||||
Name: "AppCenter/Core",
|
||||
Version: "4.2.0",
|
||||
},
|
||||
{
|
||||
ID: "AppCenter/Crashes/4.2.0",
|
||||
ID: "AppCenter/Crashes@4.2.0",
|
||||
Name: "AppCenter/Crashes",
|
||||
Version: "4.2.0",
|
||||
DependsOn: []string{
|
||||
"AppCenter/Core/4.2.0",
|
||||
"AppCenter/Core@4.2.0",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "KeychainAccess/4.2.1",
|
||||
ID: "KeychainAccess@4.2.1",
|
||||
Name: "KeychainAccess",
|
||||
Version: "4.2.1",
|
||||
},
|
||||
|
||||
@@ -57,6 +57,17 @@ func (p *PackageURL) Package() *ftypes.Package {
|
||||
}
|
||||
}
|
||||
|
||||
// CocoaPods purl has no namespace, but has subpath
|
||||
// https://github.com/package-url/purl-spec/blob/a748c36ad415c8aeffe2b8a4a5d8a50d16d6d85f/PURL-TYPES.rst#cocoapods
|
||||
if p.Type == packageurl.TypeCocoapods && p.Subpath != "" {
|
||||
// CocoaPods uses <moduleName>/<submoduleName> format for package name
|
||||
// e.g. `pkg:cocoapods/GoogleUtilities@7.5.2#NSData+zlib` => `GoogleUtilities/NSData+zlib`
|
||||
pkg.Name = strings.Join([]string{
|
||||
p.Name,
|
||||
p.Subpath,
|
||||
}, "/")
|
||||
}
|
||||
|
||||
if p.Type == packageurl.TypeRPM {
|
||||
rpmVer := version.NewVersion(p.Version)
|
||||
pkg.Release = rpmVer.Release()
|
||||
@@ -109,6 +120,8 @@ func (p *PackageURL) PackageType() string {
|
||||
case packageurl.TypeNuget:
|
||||
return ftypes.NuGet
|
||||
case packageurl.TypeSwift:
|
||||
return ftypes.Swift
|
||||
case packageurl.TypeCocoapods:
|
||||
return ftypes.Cocoapods
|
||||
case packageurl.TypeHex:
|
||||
return ftypes.Hex
|
||||
@@ -154,6 +167,7 @@ func NewPackageURL(t string, metadata types.Metadata, pkg ftypes.Package) (Packa
|
||||
name := pkg.Name
|
||||
ver := utils.FormatVersion(pkg)
|
||||
namespace := ""
|
||||
subpath := ""
|
||||
|
||||
switch ptype {
|
||||
case packageurl.TypeRPM:
|
||||
@@ -180,6 +194,10 @@ func NewPackageURL(t string, metadata types.Metadata, pkg ftypes.Package) (Packa
|
||||
namespace, name = parseGolang(name)
|
||||
case packageurl.TypeNPM:
|
||||
namespace, name = parseNpm(name)
|
||||
case packageurl.TypeSwift:
|
||||
namespace, name = parseSwift(name)
|
||||
case packageurl.TypeCocoapods:
|
||||
name, subpath = parseCocoapods(name)
|
||||
case packageurl.TypeOCI:
|
||||
purl, err := parseOCI(metadata)
|
||||
if err != nil {
|
||||
@@ -189,7 +207,7 @@ func NewPackageURL(t string, metadata types.Metadata, pkg ftypes.Package) (Packa
|
||||
}
|
||||
|
||||
return PackageURL{
|
||||
PackageURL: *packageurl.NewPackageURL(ptype, namespace, name, ver, qualifiers, ""),
|
||||
PackageURL: *packageurl.NewPackageURL(ptype, namespace, name, ver, qualifiers, subpath),
|
||||
FilePath: pkg.FilePath,
|
||||
}, nil
|
||||
}
|
||||
@@ -306,6 +324,22 @@ func parseComposer(pkgName string) (string, string) {
|
||||
return parsePkgName(pkgName)
|
||||
}
|
||||
|
||||
// ref. https://github.com/package-url/purl-spec/blob/a748c36ad415c8aeffe2b8a4a5d8a50d16d6d85f/PURL-TYPES.rst#swift
|
||||
func parseSwift(pkgName string) (string, string) {
|
||||
return parsePkgName(pkgName)
|
||||
}
|
||||
|
||||
// ref. https://github.com/package-url/purl-spec/blob/a748c36ad415c8aeffe2b8a4a5d8a50d16d6d85f/PURL-TYPES.rst#cocoapods
|
||||
func parseCocoapods(pkgName string) (string, string) {
|
||||
var subpath string
|
||||
index := strings.Index(pkgName, "/")
|
||||
if index != -1 {
|
||||
subpath = pkgName[index+1:]
|
||||
pkgName = pkgName[:index]
|
||||
}
|
||||
return pkgName, subpath
|
||||
}
|
||||
|
||||
// ref. https://github.com/package-url/purl-spec/blob/a748c36ad415c8aeffe2b8a4a5d8a50d16d6d85f/PURL-TYPES.rst#npm
|
||||
func parseNpm(pkgName string) (string, string) {
|
||||
// the name must be lowercased
|
||||
@@ -330,6 +364,8 @@ func purlType(t string) string {
|
||||
case ftypes.Npm, ftypes.NodePkg, ftypes.Yarn, ftypes.Pnpm:
|
||||
return packageurl.TypeNPM
|
||||
case ftypes.Cocoapods:
|
||||
return packageurl.TypeCocoapods
|
||||
case ftypes.Swift:
|
||||
return packageurl.TypeSwift
|
||||
case ftypes.Hex:
|
||||
return packageurl.TypeHex
|
||||
|
||||
@@ -213,6 +213,40 @@ func TestNewPackageURL(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "swift package",
|
||||
typ: ftypes.Swift,
|
||||
pkg: ftypes.Package{
|
||||
ID: "github.com/apple/swift-atomics@1.1.0",
|
||||
Name: "github.com/apple/swift-atomics",
|
||||
Version: "1.1.0",
|
||||
},
|
||||
want: purl.PackageURL{
|
||||
PackageURL: packageurl.PackageURL{
|
||||
Type: packageurl.TypeSwift,
|
||||
Namespace: "github.com/apple",
|
||||
Name: "swift-atomics",
|
||||
Version: "1.1.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cocoapods package",
|
||||
typ: ftypes.Cocoapods,
|
||||
pkg: ftypes.Package{
|
||||
ID: "GoogleUtilities/NSData+zlib@7.5.2",
|
||||
Name: "GoogleUtilities/NSData+zlib",
|
||||
Version: "7.5.2",
|
||||
},
|
||||
want: purl.PackageURL{
|
||||
PackageURL: packageurl.PackageURL{
|
||||
Type: packageurl.TypeCocoapods,
|
||||
Name: "GoogleUtilities",
|
||||
Version: "7.5.2",
|
||||
Subpath: "NSData+zlib",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "os package",
|
||||
typ: os.RedHat,
|
||||
@@ -377,7 +411,6 @@ func TestNewPackageURL(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFromString(t *testing.T) {
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
purl string
|
||||
@@ -415,6 +448,19 @@ func TestFromString(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy path for coocapods",
|
||||
purl: "pkg:cocoapods/GoogleUtilities@7.5.2#NSData+zlib",
|
||||
want: purl.PackageURL{
|
||||
PackageURL: packageurl.PackageURL{
|
||||
Type: packageurl.TypeCocoapods,
|
||||
Name: "GoogleUtilities",
|
||||
Version: "7.5.2",
|
||||
Subpath: "NSData+zlib",
|
||||
Qualifiers: packageurl.Qualifiers{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy path for hex",
|
||||
purl: "pkg:hex/plug@1.14.0",
|
||||
@@ -514,3 +560,125 @@ func TestFromString(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackage(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pkgURL *purl.PackageURL
|
||||
wantPkg *ftypes.Package
|
||||
}{
|
||||
{
|
||||
name: "rpm + Qualifiers",
|
||||
pkgURL: &purl.PackageURL{
|
||||
PackageURL: packageurl.PackageURL{
|
||||
Type: packageurl.TypeRPM,
|
||||
Namespace: "redhat",
|
||||
Name: "nodejs-full-i18n",
|
||||
Version: "10.21.0-3.module_el8.2.0+391+8da3adc6",
|
||||
Qualifiers: packageurl.Qualifiers{
|
||||
{
|
||||
Key: "arch",
|
||||
Value: "x86_64",
|
||||
},
|
||||
{
|
||||
Key: "epoch",
|
||||
Value: "1",
|
||||
},
|
||||
{
|
||||
Key: "modularitylabel",
|
||||
Value: "nodejs:10:8020020200707141642:6a468ee4",
|
||||
},
|
||||
{
|
||||
Key: "distro",
|
||||
Value: "redhat-8",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantPkg: &ftypes.Package{
|
||||
Name: "nodejs-full-i18n",
|
||||
Version: "10.21.0",
|
||||
Release: "3.module_el8.2.0+391+8da3adc6",
|
||||
Arch: "x86_64",
|
||||
Epoch: 1,
|
||||
Modularitylabel: "nodejs:10:8020020200707141642:6a468ee4",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "composer with namespace",
|
||||
pkgURL: &purl.PackageURL{
|
||||
PackageURL: packageurl.PackageURL{
|
||||
Type: packageurl.TypeComposer,
|
||||
Namespace: "symfony",
|
||||
Name: "contracts",
|
||||
Version: "v1.0.2",
|
||||
},
|
||||
},
|
||||
wantPkg: &ftypes.Package{
|
||||
Name: "symfony/contracts",
|
||||
Version: "v1.0.2",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "maven with namespace",
|
||||
pkgURL: &purl.PackageURL{
|
||||
PackageURL: packageurl.PackageURL{
|
||||
Type: packageurl.TypeMaven,
|
||||
Namespace: "org.springframework",
|
||||
Name: "spring-core",
|
||||
Version: "5.0.4.RELEASE",
|
||||
Qualifiers: packageurl.Qualifiers{},
|
||||
},
|
||||
},
|
||||
wantPkg: &ftypes.Package{
|
||||
Name: "org.springframework:spring-core",
|
||||
Version: "5.0.4.RELEASE",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cocoapods with subpath",
|
||||
pkgURL: &purl.PackageURL{
|
||||
PackageURL: packageurl.PackageURL{
|
||||
Type: packageurl.TypeCocoapods,
|
||||
Version: "4.2.0",
|
||||
Name: "AppCenter",
|
||||
Subpath: "Analytics",
|
||||
Qualifiers: packageurl.Qualifiers{},
|
||||
},
|
||||
},
|
||||
wantPkg: &ftypes.Package{
|
||||
Name: "AppCenter/Analytics",
|
||||
Version: "4.2.0",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "wrong epoch",
|
||||
pkgURL: &purl.PackageURL{
|
||||
PackageURL: packageurl.PackageURL{
|
||||
Type: packageurl.TypeRPM,
|
||||
Namespace: "redhat",
|
||||
Name: "acl",
|
||||
Version: "2.2.53-1.el8",
|
||||
Qualifiers: packageurl.Qualifiers{
|
||||
{
|
||||
Key: "epoch",
|
||||
Value: "wrong",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantPkg: &ftypes.Package{
|
||||
Name: "acl",
|
||||
Version: "2.2.53",
|
||||
Release: "1.el8",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := tt.pkgURL.Package()
|
||||
assert.Equal(t, tt.wantPkg, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user