-
-
Notifications
You must be signed in to change notification settings - Fork 267
#1 Query cve-search' database for package vulnerabilities #2
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
Conversation
pombredanne
left a comment
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.
Here is some quick feedback
test_api_data.py
Outdated
| api.urlopen.return_value = test_data | ||
| api.output_cve_id() | ||
|
|
||
| assert api.output_cve_id.data["data"]["item"] == "CVE-2007-1004" No newline at end of file |
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.
You want a line return an the end of every files.
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.
Gotcha
test_api_data.py
Outdated
|
|
||
| def test_output_cve_id(): | ||
|
|
||
| ##BUG## |
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.
What is this comment about? and why an empty line before?
api_data.py
Outdated
| vulnerabilities of the requested package. If | ||
| vulnerability exists, outputs cve-id(s). | ||
| """ | ||
| package_name = raw_input('Enter package name: ') |
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.
You should rather use args instead and not expect user input at all.
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.
Yes, I was developing it into, command line based args and flags.
Will try to get it done in the next commit, by today.
api_data.py
Outdated
| raw_data = urlopen(url).read() | ||
| data = json.loads(raw_data) | ||
|
|
||
| if len(data) > 0: |
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.
you could use instead if data: to the same effect
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.
You are fast. 😛
api_data.py
Outdated
| data = json.loads(raw_data) | ||
|
|
||
| if len(data) > 0: | ||
| print 'Vulnerabilties Found:\n' |
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.
You should rather have a function that return data and a main that accepts command line args and deal with printing.
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.
Yes, as stated in the previous comment. Working on that.
api_data.py
Outdated
| from urllib import urlopen | ||
|
|
||
| def output_cve_id(): | ||
| """Takes as input, a package name, package version. |
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.
Use Take rather than Takes also start the docstring on the next line.
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.
Gotcha
test_api_data.py
Outdated
| @@ -0,0 +1,50 @@ | |||
| import api_data as api | |||
|
|
|||
| from mock import Mock | |||
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.
If you use packages for tests, then they should be at least part of some tests requirements file.
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.
I'll add that to the requirements.txt.
|
Couple comments on style:
|
api_data.py
Outdated
| print ('No vulnerabilites found') | ||
|
|
||
| if __name__ == '__main__': | ||
| output_cve_id() No newline at end of file |
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.
@pombredanne I had added a line after the EOF, I think i deleted it un-consiously. Will be more alert next time
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.
@kartiksibal as I mentioned, run pycodestyle on your code before committing, it will let you know about those type of issues.
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.
@tdruez won't forget it next time 😄
pombredanne
left a comment
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.
Looking good overall
api_data.py
Outdated
| from urllib import urlopen | ||
|
|
||
| def output_cve_id(type=None, name=None, version=None): | ||
| """Takes as input, a package name, package version. |
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.
I guess my previous commit comment on this still applies? ;)
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.
Shoot!
api_data.py
Outdated
| url = 'https://cve.circl.lu/api/search/' + package_name + package_ver | ||
|
|
||
| if version: | ||
| url = 'https://cve.circl.lu/api/search/' + name + version |
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.
what is there is no name? Also you might want to use the .format() syntax rather than a +
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.
@pombredanne The name is a basic necessity. I was thinking of maybe keeping the whole function in a try-catch block, since if the name is none. We have nothing to search?
api_data.py
Outdated
| vulnerabilities of the requested package. If | ||
| vulnerability exists, outputs cve-id(s). | ||
| """ | ||
| if version: |
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.
What is there name is None?
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.
This code will crash. Write some tests... and you will see.
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.
@pombredanne As mentioned above, i wasn't sure if going with, keeping the function in a try-except block an effective way to counter this?
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.
@kartiksibal nope, you should test the values you get:
Did you get a name and version? --> query for name+version
Did you get only a name? --> query for name
Did you get only a version --> query for version
Eventually you could check if this can be searched more specifically in CPEs?
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.
@pombredanne A query for just version without a package name isn't possible right?
I'll fix this in the next commit.
api_data.py
Outdated
| raw_data = urlopen(url).read() | ||
| data = json.loads(raw_data) | ||
|
|
||
| if data: |
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.
Just return data, do not print it there. Print after calling the function
api_data.py
Outdated
| """ | ||
| if version: | ||
| url = 'https://cve.circl.lu/api/search/' + name + version | ||
| url = ('https://cve.circl.lu/api/search/{}/{}').format(name,version) |
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.
Here the parenthesis around the string are not needed: '{}'.format()
Since we are using Python 3.6+, feel free to use the format string as in:
f'https://cve.circl.lu/api/search/{name}/{version}'
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.
@tdruez Pro tip!
Thanks 😄
api_data.py
Outdated
| from urllib.request import urlopen | ||
|
|
||
| def output_cve_id(type=None, name=None, version=None): | ||
| """Take as input, a package name, package version. |
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.
Minor style point: start the doc on the next line as in
"""
Take as input, a package name....
Also it is best to start with what you return rather than what you accept
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
| @@ -0,0 +1,32 @@ | |||
| #!/usr/bin/env python | |||
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.
You are missing a license header ;)
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!
api_data.py
Outdated
| if data: | ||
| for item in data['data']: | ||
| return item['id'] | ||
| else: |
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.
else, return None is not needed, this is the default in Python
api_data.py
Outdated
| vulnerability exists, outputs cve-id(s). | ||
| """ | ||
| if not name: | ||
| return None |
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.
return is enough, None is the default
test_api_data.py
Outdated
| ''' | ||
|
|
||
| def test_output_cve_id(): | ||
| #BUG: |
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.
What is this comment?
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.
I guess you did not remove this?
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.
@pombredanne I haven't been able to find a workaround. it'd be great if you took a look.
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.
@kartiksibal the think I am not comfy with is the #BUG comment which is meaningless... either you explain in a full narrative comment what the bug is or you remove the #BUG line ;)
|
@kartiksibal please fix the remaining issues reported by @pombredanne so we can merge this PR. |
api_data.py
Outdated
| from urllib.request import urlopen | ||
|
|
||
| def output_cve_id(type=None, name=None, version=None): | ||
| """Take as input, a package name, package version. |
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.
type is never used, it should be removed.
Since you always need a name, no need to make it optional, remove the =None.
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.
I had a talk with @pombredanne regarding this.
This is the way he suggested it to be.
We can discuss this further? :-)
api_data.py
Outdated
| vulnerabilities of the requested package. If | ||
| vulnerability exists, outputs cve-id(s). | ||
| """ | ||
| id = [] |
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.
In Python id is a built-in function https://docs.python.org/2/library/functions.html#id, you should avoid using it for your variable names.
Also, since you are naming a list, you should use the plural: ids.
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.
Gotcha!
api_data.py
Outdated
| raw_data = urlopen(url).read() | ||
| data = json.loads(raw_data) | ||
|
|
||
| if data and name and not version: |
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.
You already tested if not name: above, no need to test it again here.
api_data.py
Outdated
|
|
||
| return id | ||
|
|
||
| if __name__ == '__main__': |
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.
You can remove this section, this file is not meant to be run as a script but called as a library.
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.
@tdruez I agree with you. But don't you think the api code has a use case in it's own too?
If someone doesn't want to use the django app and just get data?
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.
Right now, in that state it has absolutely no value. There's a usecase for using vulnerablecode as a script, but we'll get to it later, with a proper cli.
api_data.py
Outdated
| return id | ||
|
|
||
| if data and version and name: | ||
| for item in data: |
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.
This section is duplicated with the previous one. The only difference seems to be data['data'] in the first case and data. You should use the if to set the proper content in the variable, then us the same loop.
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.
@tdruez The JSON output changes if a version is added to the URL. Hence, this added part.
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.
As you said, the variable content changes, but the iteration logic stay the same.
Thus, you need to set the proper variable but use the same loop.
| import json | ||
| from urllib.request import urlopen | ||
|
|
||
| def data_cve_circl(name, version=None): |
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.
Surround top-level function and class definitions with two blank lines.
api_data.py
Outdated
| extracted_data = [] | ||
|
|
||
| if version: | ||
| data = data |
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.
This line has no value. The following is enough:
if not version:
data = data['data']
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.
Also, I think this section of the code belongs to data_cve_circl().
The extraction logic should not care about the version.
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.
@tdruez The data that the API returns, differs, in the case a version is specified. Hence, the version check is necessary.
api_data.py
Outdated
| data = data['data'] | ||
|
|
||
| for item in data: | ||
| results = {} |
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.
This should be replaced by a dict comprehension:
{key: value for (key, value) in iterable}
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.
results = {}
{results[name]: item[name] for name in fields_names for item in data}
It is kind of erratic, but I am getting a KeyError. I am unable to debug the issue, could you guide?
Thanks
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.
Try this instead:
results = {name: item[name] for name in fields_names}
extracted_data.append(results)
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.
@tdruez You missed for item in data and oddly, it is storing just a single entry.
I think we should let go off the dict. comprehension because we need a try except block incase of a KeyError which tends to pop up if a key is missing somewhere in the data. This shouldn't happen, since the data obviously follows a set pattern. But, there is something fishy in the backend.
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.
Of course the for item in data is still required to build the list. My point is about the dict.
Anyway, keep it the way it works for now, this is not a required change, just nice to have.
| url = f'https://cve.circl.lu/api/search/{name}' | ||
|
|
||
| if version: | ||
| url += f'/{version}' |
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.
This f is Python 3-only, right? I guess this is OK as we said we would only support Python3, right?
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.
Yes, that was an update in 3.6 and yes as you said earlier to support 3.6+. So, this can stay.
| def extract_fields(data, fields_names, version=False): | ||
| """ | ||
| Extracts requested data fields using data generated by | ||
| cve-search' api. Takes as input data, fields requested |
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.
you are missing a quote.
api_data.py
Outdated
|
|
||
| def extract_fields(data, fields_names, version=False): | ||
| """ | ||
| Extracts requested data fields using data generated by |
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.
Please use singular order-style Extract and not Extracts and start your doc with what is returned rather than what it does.
test_api_data.py
Outdated
| ''' | ||
|
|
||
| def test_output_cve_id(): | ||
| #BUG: |
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.
I guess you did not remove this?
test_api_data.py
Outdated
| @@ -0,0 +1,49 @@ | |||
| import api_data as api | |||
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.
You are also missing a license header
c4b7974 to
7560ac5
Compare
7560ac5 to
09413f9
Compare
* Add PEP 517/518 pyproject.toml file * Add setuptools_scm to handle versioning * Add setup.py content to setup.cfg * Update setup.py to act as a shim (so pip install -e works) Addresses: #2 Signed-off-by: Steven Esser <sesser@nexb.com>
Signed-off-by: Kartik Sibal kartiksibal@gmail.com