Skip to content

Commit

Permalink
feat: index known cpes for PHP extensions
Browse files Browse the repository at this point in the history
Indexes known CPEs from `pecl.php.net` and `pear.php.net`

Signed-off-by: Weston Steimel <commits@weston.slmail.me>
  • Loading branch information
westonsteimel committed Apr 15, 2024
1 parent 587690b commit f28023a
Show file tree
Hide file tree
Showing 7 changed files with 260 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,19 @@
"zjjserver": "cpe:2.3:a:zjjserver_project:zjjserver:*:*:*:*:*:node.js:*:*",
"zwserver": "cpe:2.3:a:zwserver_project:zwserver:*:*:*:*:*:node.js:*:*"
},
"php_pear": {
"Archive_Tar": "cpe:2.3:a:php:pear_archive_tar:*:*:*:*:*:*:*:*",
"HTML_AJAX": "cpe:2.3:a:pear:html_ajax:*:*:*:*:*:*:*:*",
"HTML_QuickForm": "cpe:2.3:a:html_quickform_project:html_quickform:*:*:*:*:*:*:*:*",
"PEAR": "cpe:2.3:a:php:pear:*:*:*:*:*:*:*:*",
"XML_RPC": "cpe:2.3:a:php:xml_rpc:*:*:*:*:*:pear:*:*"
},
"php_pecl": {
"imagick": "cpe:2.3:a:php:imagick:*:*:*:*:*:*:*:*",
"memcached": "cpe:2.3:a:php:memcached:*:*:*:*:*:*:*:*",
"pecl_http": "cpe:2.3:a:php:pecl_http:*:*:*:*:*:*:*:*",
"xhprof": "cpe:2.3:a:php:xhprof:*:*:*:*:*:*:*:*"
},
"pypi": {
"0.0.1": "cpe:2.3:a:pypi:pypi:*:*:*:*:*:*:*:*",
"AAmiles": "cpe:2.3:a:pypi:aamiles:*:*:*:*:*:pypi:*:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ const (
prefixForPyPIPackages = "https://pypi.org/project/"
prefixForJenkinsPlugins = "https://github.com/jenkinsci/"
prefixForRustCrates = "https://crates.io/crates/"
prefixForPHPPear = "https://pear.php.net/"
prefixForPHPPearHTTP = "http://pear.php.net/"
prefixForPHPPecl = "https://pecl.php.net/"
prefixForPHPPeclHTTP = "http://pecl.php.net/"
)

// indexCPEList creates an index of CPEs by ecosystem.
Expand Down Expand Up @@ -141,6 +145,12 @@ func indexCPEList(list CpeList) *dictionary.Indexed {

case strings.HasPrefix(ref, prefixForRustCrates):
addEntryForRustCrate(indexed, ref, cpeItemName)

case strings.HasPrefix(ref, prefixForPHPPear), strings.HasPrefix(ref, prefixForPHPPearHTTP):
addEntryForPHPPearPackage(indexed, ref, cpeItemName)

case strings.HasPrefix(ref, prefixForPHPPecl), strings.HasPrefix(ref, prefixForPHPPeclHTTP):
addEntryForPHPPeclPackage(indexed, ref, cpeItemName)
}
}
}
Expand Down Expand Up @@ -228,3 +238,63 @@ func addEntryForNPMPackage(indexed *dictionary.Indexed, ref string, cpeItemName

indexed.EcosystemPackages[dictionary.EcosystemNPM][ref] = cpeItemName
}

func phpExtensionPackageFromURLFragment(ref string) string {
if strings.HasPrefix(ref, "package/") { // package/HTML_QuickForm/download
ref = strings.TrimPrefix(ref, "package/")
components := strings.Split(ref, "/")

if len(components) < 1 {
return ""
}

ref = components[0]
} else if strings.Contains(ref, "?package=") { // package-changelog.php?package=xhprof&amp;release=0.9.4
components := strings.Split(ref, "?package=")

if len(components) < 2 {
return ""
}

components = strings.Split(components[1], "&")
if len(components) < 2 {
return ""
}

ref = components[0]
}

return ref
}

func addEntryForPHPPearPackage(indexed *dictionary.Indexed, ref string, cpeItemName string) {
ref = strings.TrimPrefix(ref, prefixForPHPPear)
ref = strings.TrimPrefix(ref, prefixForPHPPearHTTP)
ref = phpExtensionPackageFromURLFragment(ref)

if ref == "" {
return
}

if _, ok := indexed.EcosystemPackages[dictionary.EcosystemPHPPear]; !ok {
indexed.EcosystemPackages[dictionary.EcosystemPHPPear] = make(dictionary.Packages)
}

indexed.EcosystemPackages[dictionary.EcosystemPHPPear][ref] = cpeItemName
}

func addEntryForPHPPeclPackage(indexed *dictionary.Indexed, ref string, cpeItemName string) {
ref = strings.TrimPrefix(ref, prefixForPHPPecl)
ref = strings.TrimPrefix(ref, prefixForPHPPeclHTTP)
ref = phpExtensionPackageFromURLFragment(ref)

if ref == "" {
return
}

if _, ok := indexed.EcosystemPackages[dictionary.EcosystemPHPPecl]; !ok {
indexed.EcosystemPackages[dictionary.EcosystemPHPPecl] = make(dictionary.Packages)
}

indexed.EcosystemPackages[dictionary.EcosystemPHPPecl][ref] = cpeItemName
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,58 @@ func Test_addEntryFuncs(t *testing.T) {
},
},
},
{
name: "addEntryForPHPPeclPackage",
addEntryFunc: addEntryForPHPPeclPackage,
inputRef: "https://pecl.php.net/package/imagick/something/something/v4007.0",
inputCpeItemName: "cpe:2.3:a:php:imagick:*:*:*:*:*:*:*:*",
expectedIndexed: dictionary.Indexed{
EcosystemPackages: map[string]dictionary.Packages{
dictionary.EcosystemPHPPecl: {
"imagick": "cpe:2.3:a:php:imagick:*:*:*:*:*:*:*:*",
},
},
},
},
{
name: "addEntryForPHPPeclPackage http changelog",
addEntryFunc: addEntryForPHPPeclPackage,
inputRef: "http://pecl.php.net/package-changelog.php?package=memcached&amp;release",
inputCpeItemName: "cpe:2.3:a:php:memcached:*:*:*:*:*:*:*:*",
expectedIndexed: dictionary.Indexed{
EcosystemPackages: map[string]dictionary.Packages{
dictionary.EcosystemPHPPecl: {
"memcached": "cpe:2.3:a:php:memcached:*:*:*:*:*:*:*:*",
},
},
},
},
{
name: "addEntryForPHPPearPackage",
addEntryFunc: addEntryForPHPPearPackage,
inputRef: "https://pear.php.net/package/PEAR/download",
inputCpeItemName: "cpe:2.3:a:php:pear:*:*:*:*:*:*:*:*",
expectedIndexed: dictionary.Indexed{
EcosystemPackages: map[string]dictionary.Packages{
dictionary.EcosystemPHPPear: {
"PEAR": "cpe:2.3:a:php:pear:*:*:*:*:*:*:*:*",
},
},
},
},
{
name: "addEntryForPHPPearPackage http changelog",
addEntryFunc: addEntryForPHPPearPackage,
inputRef: "http://pear.php.net/package-changelog.php?package=abcdefg&amp;release",
inputCpeItemName: "cpe:2.3:a:php:abcdefg:*:*:*:*:*:*:*:*",
expectedIndexed: dictionary.Indexed{
EcosystemPackages: map[string]dictionary.Packages{
dictionary.EcosystemPHPPear: {
"abcdefg": "cpe:2.3:a:php:abcdefg:*:*:*:*:*:*:*:*",
},
},
},
},
}

for _, tt := range tests {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@
"unicode": "cpe:2.3:a:unicode_project:unicode:*:*:*:*:*:node.js:*:*",
"unicorn-list": "cpe:2.3:a:unicorn-list_project:unicorn-list:*:*:*:*:*:node.js:*:*"
},
"php_pear": {
"HTML_QuickForm": "cpe:2.3:a:html_quickform_project:html_quickform:*:*:*:*:*:*:*:*",
"PEAR": "cpe:2.3:a:php:pear:*:*:*:*:*:*:*:*",
"XML_RPC": "cpe:2.3:a:php:xml_rpc:*:*:*:*:*:pear:*:*"
},
"php_pecl": {
"imagick": "cpe:2.3:a:php:imagick:*:*:*:*:*:*:*:*",
"memcached": "cpe:2.3:a:php:memcached:*:*:*:*:*:*:*:*",
"xhprof": "cpe:2.3:a:php:xhprof:*:*:*:*:*:*:*:*"
},
"rubygems": {
"openssl": "cpe:2.3:a:ruby-lang:openssl:*:*:*:*:*:*:*:*"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24873,4 +24873,114 @@
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:zzzcms:zzzphp:2.1.0:*:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:php:xhprof:0.9.1">
<title xml:lang="en-US">PHP XHProf 0.9.1</title>
<references>
<reference href="http://pecl.php.net/package-changelog.php?package=xhprof&amp;release=0.9.4">product changelog</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:php:xhprof:0.9.1:*:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:php:xhprof:0.9.2">
<title xml:lang="en-US">PHP XHProf 0.9.2</title>
<references>
<reference href="http://pecl.php.net/package-changelog.php?package=xhprof&amp;release=0.9.4">product changelog</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:php:xhprof:0.9.2:*:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:php:xhprof:0.9.3">
<title xml:lang="en-US">PHP XHProf 0.9.3</title>
<references>
<reference href="http://pecl.php.net/package-changelog.php?package=xhprof&amp;release=0.9.4">product changelog</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:php:xhprof:0.9.3:*:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:php:memcached:0.1.0">
<title xml:lang="en-US">PHP memecached 0.1.0</title>
<references>
<reference href="https://pecl.php.net/package-changelog.php?package=memcached&amp;release">Change Log</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:php:memcached:0.1.0:*:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:php:memcached:0.1.2">
<title xml:lang="en-US">PHP memecached 0.1.2</title>
<references>
<reference href="https://pecl.php.net/package-changelog.php?package=memcached&amp;release">Change Log</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:php:memcached:0.1.2:*:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:php:memcached:0.1.3">
<title xml:lang="en-US">PHP memecached 0.1.3</title>
<references>
<reference href="https://pecl.php.net/package-changelog.php?package=memcached&amp;release">Change Log</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:php:memcached:0.1.3:*:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:php:imagick:3.3.0">
<title xml:lang="en-US">PHP Imagick 3.3.0</title>
<references>
<reference href="http://pecl.php.net/package/imagick">Version</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:php:imagick:3.3.0:*:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:php:imagick:3.4.0:-">
<title xml:lang="en-US">PHP Imagick 3.4.0</title>
<references>
<reference href="http://pecl.php.net/package/imagick">Version</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:php:imagick:3.4.0:-:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:php:xml_rpc:1.4.4::~~~pear~~">
<title xml:lang="en-US">PHP XML_RPC 1.4.4 for Pear</title>
<references>
<reference href="https://pear.php.net/package/XML_RPC/download/">Version</reference>
<reference href="https://pear.php.net/package/XML_RPC/">Product</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:php:xml_rpc:1.4.4:*:*:*:*:pear:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:php:xml_rpc:1.4.5::~~~pear~~">
<title xml:lang="en-US">PHP XML_RPC 1.4.5 for Pear</title>
<references>
<reference href="https://pear.php.net/package/XML_RPC/download/">Version</reference>
<reference href="https://pear.php.net/package/XML_RPC/">Product</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:php:xml_rpc:1.4.5:*:*:*:*:pear:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:php:xml_rpc:1.4.6::~~~pear~~">
<title xml:lang="en-US">PHP XML_RPC 1.4.6 for Pear</title>
<references>
<reference href="https://pear.php.net/package/XML_RPC/download/">Version</reference>
<reference href="https://pear.php.net/package/XML_RPC/">Product</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:php:xml_rpc:1.4.6:*:*:*:*:pear:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:php:pear:1.0:-">
<title xml:lang="en-US">PHP PEAR 1.0</title>
<references>
<reference href="https://pear.php.net/package/PEAR/download/">Change Log</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:php:pear:1.0:-:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:php:pear:1.0:b1">
<title xml:lang="en-US">PHP PEAR 1.0 Beta 1</title>
<references>
<reference href="https://pear.php.net/package/PEAR/download/">Change Log</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:php:pear:1.0:b1:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:html_quickform_project:html_quickform:2.0">
<title xml:lang="en-US">HTML_QuickForm project HTML_QuickForm 2.0</title>
<references>
<reference href="http://pear.php.net/package/HTML_QuickForm/">Project</reference>
<reference href="http://pear.php.net/package/HTML_QuickForm/download">Version</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:html_quickform_project:html_quickform:2.0:*:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:html_quickform_project:html_quickform:2.1">
<title xml:lang="en-US">HTML_QuickForm project HTML_QuickForm 2.1</title>
<references>
<reference href="http://pear.php.net/package/HTML_QuickForm/">Project</reference>
<reference href="http://pear.php.net/package/HTML_QuickForm/download">Version</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:html_quickform_project:html_quickform:2.1:*:*:*:*:*:*:*"/>
</cpe-item>
</cpe-list>
2 changes: 2 additions & 0 deletions syft/pkg/cataloger/internal/cpegenerate/dictionary/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const (
EcosystemNPM = "npm"
EcosystemRubyGems = "rubygems"
EcosystemPyPI = "pypi"
EcosystemPHPPear = "php_pear"
EcosystemPHPPecl = "php_pecl"
EcosystemJenkinsPlugins = "jenkins_plugins"
EcosystemRustCrates = "rust_crates"
)
Expand Down
3 changes: 3 additions & 0 deletions syft/pkg/cataloger/internal/cpegenerate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ func FromDictionaryFind(p pkg.Package) (cpe.CPE, bool) {
case pkg.RustPkg:
cpeString, ok = dict.EcosystemPackages[dictionary.EcosystemRustCrates][p.Name]

case pkg.PhpPeclPkg:
cpeString, ok = dict.EcosystemPackages[dictionary.EcosystemPHPPecl][p.Name]

default:
// The dictionary doesn't support this package type yet.
return cpe.CPE{}, false
Expand Down

0 comments on commit f28023a

Please sign in to comment.