-
Notifications
You must be signed in to change notification settings - Fork 214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat: Add CVE support to Snyk datasource #1405
Feat: Add CVE support to Snyk datasource #1405
Conversation
Signed-off-by: Shenoy <[email protected]>
…ed from the cve url Signed-off-by: Shenoy <[email protected]>
Signed-off-by: Shenoy <[email protected]>
Signed-off-by: Shenoy <[email protected]>
Signed-off-by: Shenoy <[email protected]>
Signed-off-by: Shenoy <[email protected]>
Oops looks like one test related to formatting is failing - Black style check failed. Will try to fix that |
@shravankshenoy you can just run |
Signed-off-by: Shenoy <[email protected]>
Signed-off-by: Shenoy <[email protected]>
Thanks @ziadhany . All the tests are passing now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @shravankshenoy. This is a good start.
Please take a look at the suggestions below.
vulntotal/datasources/snyk.py
Outdated
pkg_name = package_url_split[1].split(":")[1] | ||
namespace = package_url_split[1].split(":")[0] | ||
|
||
elif pkg_type in ("golang", "composer"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PURL creation for golang needs to be properly handled. Take a look at the example below.
For the snyk url https://security.snyk.io/package/golang/github.com%2Fgoauthentik%2Fauthentik%2Fauthentik%2Fproviders%2Foauth2%2Fviews
the corresponding purl would be
PackageURL(
type='golang',
namespace='github.com/goauthentik/authentik/authentik/providers/oauth2',
name='views',
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for highlighting this. I have modified the code so that namespace for Go packages is captured correctly.
vulntotal/datasources/snyk.py
Outdated
def generate_purl(package_advisory_url): | ||
""" | ||
Generates purl from Package advisory url. | ||
|
||
Parameters: | ||
package_advisory_url: URL of the package on Snyk. | ||
|
||
Returns: | ||
A PackageURL instance representing the package | ||
""" | ||
package_advisory_url = unquote_plus( | ||
package_advisory_url.replace("https://security.snyk.io/package/", "") | ||
) | ||
|
||
package_url_split = package_advisory_url.split("/") | ||
pkg_type = package_url_split[0] | ||
|
||
pkg_name = None | ||
namespace = None | ||
version = None | ||
qualifiers = {} | ||
|
||
if pkg_type == "maven": | ||
pkg_name = package_url_split[1].split(":")[1] | ||
namespace = package_url_split[1].split(":")[0] | ||
|
||
elif pkg_type in ("golang", "composer"): | ||
if package_url_split[1] == "github.com": | ||
pkg_name = package_url_split[-2] | ||
namespace = f"{package_url_split[1]}/{package_url_split[2]}" | ||
version = package_url_split[-1] | ||
else: | ||
pkg_name = package_url_split[-1] | ||
namespace = package_url_split[-2] | ||
|
||
elif pkg_type == "linux": | ||
pkg_name = package_url_split[-1] | ||
qualifiers["distro"] = package_url_split[1] | ||
|
||
else: | ||
pkg_name = package_url_split[-1] | ||
|
||
return PackageURL( | ||
type=pkg_type, name=pkg_name, namespace=namespace, version=version, qualifiers=qualifiers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We must explicitly handle the PURL creation for each ecosystem from the Snyk URL.
For a better understanding on how to create a PURL for a particular ecosystem, you should check https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for sharing this. I have tried my best to make sure the purl-spec is followed properly now, but let me know if I missed something.
Signed-off-by: Shenoy <[email protected]>
Signed-off-by: Shenoy <[email protected]>
Thanks a lot for reviewing the code. It not only helped me understand purl-spec much better, but also helped while wrtitng code for some of the other PRs. As a positive side effect of this change, when I ran the code for CVE-2024-23641, it now shows the namespaces, unlike before where namespaces were null. Let me know if any further changes required, would be glad to the the needful :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shravankshenoy see few suggestions below.
vulntotal/datasources/snyk.py
Outdated
elif pkg_type in ("cocoapods", "hex", "nuget", "pip", "rubygems", "unmanaged"): | ||
pkg_name = package_url_split[-1] | ||
|
||
return PackageURL(type=pkg_type, name=pkg_name, namespace=namespace) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before returning a PURL, make sure that we have the bare minimum type
and name
available, without these PURL creation will fail. In the event that, for some reason, we are not able to get the type
and name
, log a warning and skip the advisory for this package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Added an if condition which logs an error if type or name is missing. Also datasource_advisory_from_cve
function has been modified such that if the generate_purl
function returns None, the advisory is skipped
vulntotal/datasources/snyk.py
Outdated
elif pkg_type == "golang": | ||
if package_url_split[1] == "github.com": | ||
ns_start = package_advisory_url.find("github.com") | ||
ns_end = package_advisory_url.rfind("/") | ||
namespace = package_advisory_url[ns_start:ns_end] | ||
pkg_name = package_url_split[-1] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not given that a Go package will always be on GitHub. For instance, Go package https://security.snyk.io/package/golang/blitiri.com.ar%2Fgo%2Fchasquid%2Finternal%2Fsmtp, will not be properly handled by above highlighted code.
elif pkg_type == "golang": | |
if package_url_split[1] == "github.com": | |
ns_start = package_advisory_url.find("github.com") | |
ns_end = package_advisory_url.rfind("/") | |
namespace = package_advisory_url[ns_start:ns_end] | |
pkg_name = package_url_split[-1] | |
elif pkg_type == "golang": | |
pkg_name = package_url_split[-1] | |
namespace = "/".join(package_url_split[1:-1]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
…prove error handling Signed-off-by: Shenoy <[email protected]>
Signed-off-by: Shenoy <[email protected]>
Thanks for reviewing the code. Made all the requested changes. While working on these changes, I also realized that I had somehow missed on following the purl spec properly. So I have used the dictionary which we get by calling |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks++, LGTM!
* Add function to generate purl from package advisory url Signed-off-by: Shenoy <[email protected]> * Add functions to generate cve url and parse the html advisory generated from the cve url Signed-off-by: Shenoy <[email protected]> * Add function to SnykDataSource class to get advisories from cve Signed-off-by: Shenoy <[email protected]> * Add tests and test data for parse_cve_advisory_html function Signed-off-by: Shenoy <[email protected]> * Add test for generate_purl function Signed-off-by: Shenoy <[email protected]> * Remove to_dict in snyk test file where not required Signed-off-by: Shenoy <[email protected]> * Format code using Black Signed-off-by: Shenoy <[email protected]> * Sort imports correctly using isort Signed-off-by: Shenoy <[email protected]> * Modify generate_purl function in snyk Signed-off-by: Shenoy <[email protected]> * Add additional tests for golang and npm Signed-off-by: Shenoy <[email protected]> * Add non-Github Go packages to test, modify generate_purl function, improve error handling Signed-off-by: Shenoy <[email protected]> * Modify generate_purl to comply with purl spec Signed-off-by: Shenoy <[email protected]> --------- Signed-off-by: Shenoy <[email protected]>
Fixes #1163
Changes Made
Added function
datasource_advisory_from_cve
to Snyk data source and other helper functions.Working
An overview of how the function works is given below
generate_payload_from_cve
function returns url for a given cvefetch
functionparse_cve_advisory_html
function extracts all the vulnerabilities and their snyk_ids and package ids from html pageextract_html_json_advisories
functiongenerate_advisory_payload
andfetch
functionsparse_html_advisory function
along with advisory_html page created in step 5, and that will return the final VendorData object with affected and fixed versionsgenerate_purl
is a helper function which generates a purl from package urlResults
Tested the app locally by printing the results yielded for CVE-2024-23641
This matches the result at https://security.snyk.io/vuln?search=CVE-2024-23641