diff --git a/vulnerabilities/scraper/rust.py b/vulnerabilities/scraper/rust.py index 46c8f47c9..04afa7c8c 100644 --- a/vulnerabilities/scraper/rust.py +++ b/vulnerabilities/scraper/rust.py @@ -28,66 +28,72 @@ def all_versions_of_crate(crate): yield version_info['num'] +def load_advisory(advisory): + affected_version_range_lists = list(advisory.get( + 'affected', {}).get('functions', {}).values()) + unaffected_version_range_list = advisory['versions'].get( + 'unaffected', []) + + patched_version_range_list = advisory['versions']['patched'] + # FIXME: Make distinction between unaffected and patched packages + # Check https://github.com/nexB/vulnerablecode/issues/144 + unaffected_version_range_list += patched_version_range_list + + have_unaffected_version_range = len(unaffected_version_range_list) != 0 + have_affected_version_range = len(affected_version_range_lists) != 0 + + if not (have_affected_version_range or have_unaffected_version_range): + return False + + vuln_id = advisory['advisory']['id'] + crate_name = advisory['advisory']['package'] + description = advisory['advisory']['description'] + reference = advisory['advisory'].get('url', '') + + all_versions = set(all_versions_of_crate(crate_name)) + affected_versions = set() + unaffected_versions = set() + + for version in all_versions: + categorised = False + for affected_version_range_list in affected_version_range_lists: + for affected_version_range in affected_version_range_list: + affected_version_range = RangeSpecifier( + affected_version_range) + if version in affected_version_range: + affected_versions.add(version) + categorised = True + break + + if have_unaffected_version_range and not categorised: + for unaffected_version_range in unaffected_version_range_list: + if version in RangeSpecifier(unaffected_version_range): + unaffected_versions.add(version) + break + + if not have_unaffected_version_range: + unaffected_versions = all_versions - affected_versions + + elif not have_affected_version_range: + affected_versions = all_versions - unaffected_versions + + return { + 'package_name': crate_name, + 'vuln_id': vuln_id, + 'fixed_versions': unaffected_versions, + 'affected_versions': affected_versions, + 'advisory': reference, + 'description': description + } + + def import_vulnerabilities(): vulnerability_package_dicts = [] for advisory in rust_crate_advisories(RUSTSEC_DB_URL): - affected_version_range_lists = list(advisory.get( - 'affected', {}).get('functions', {}).values()) - unaffected_version_range_list = advisory['versions'].get( - 'unaffected', []) - - patched_version_range_list = advisory['versions']['patched'] - # FIXME: Make distinction between unaffected and patched packages - # Check https://github.com/nexB/vulnerablecode/issues/144 - unaffected_version_range_list += patched_version_range_list - - have_unaffected_version_range = len(unaffected_version_range_list) != 0 - have_affected_version_range = len(affected_version_range_lists) != 0 - - if not (have_affected_version_range or have_unaffected_version_range): - continue - - vuln_id = advisory['advisory']['id'] - crate_name = advisory['advisory']['package'] - description = advisory['advisory']['description'] - reference = advisory['advisory'].get('url', '') - - all_versions = set(all_versions_of_crate(crate_name)) - affected_versions = set() - unaffected_versions = set() - - for version in all_versions: - categorised = False - for affected_version_range_list in affected_version_range_lists: - for affected_version_range in affected_version_range_list: - affected_version_range = RangeSpecifier( - affected_version_range) - if version in affected_version_range: - affected_versions.add(version) - categorised = True - break - - if have_unaffected_version_range and not categorised: - for unaffected_version_range in unaffected_version_range_list: - if version in RangeSpecifier(unaffected_version_range): - unaffected_versions.add(version) - break - - if not have_unaffected_version_range: - unaffected_versions = all_versions - affected_versions - - elif not have_affected_version_range: - affected_versions = all_versions - unaffected_versions - - vulnerability_package_dicts.append({ - 'package_name': crate_name, - 'vuln_id': vuln_id, - 'fixed_versions': unaffected_versions, - 'affected_versions': affected_versions, - 'advisory': reference, - 'description': description - }) + loaded_advisory = load_advisory(advisory) + if loaded_advisory: + vulnerability_package_dicts.append(loaded_advisory) return vulnerability_package_dicts diff --git a/vulnerabilities/tests/test_rust.py b/vulnerabilities/tests/test_rust.py new file mode 100644 index 000000000..895d073b0 --- /dev/null +++ b/vulnerabilities/tests/test_rust.py @@ -0,0 +1,38 @@ +# Author: Islam ElHakmi (@EslamHiko) +# Copyright (c) 2017 nexB Inc. and others. All rights reserved. +# http://nexb.com and https://github.com/nexB/vulnerablecode/ +# The VulnerableCode software is licensed under the Apache License version 2.0. +# Data generated with VulnerableCode require an acknowledgment. +# +# You may not use this software except in compliance with the License. +# You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# +# When you publish or redistribute any data created with VulnerableCode or any VulnerableCode +# derivative work, you must accompany this data with the following acknowledgment: +# +# Generated with VulnerableCode and provided on an "AS IS" BASIS, WITHOUT WARRANTIES +# OR CONDITIONS OF ANY KIND, either express or implied. No content created from +# VulnerableCode should be considered or used as legal advice. Consult an Attorney +# for any legal advice. +# VulnerableCode is a free software code scanning tool from nexB Inc. and others. +# Visit https://github.com/nexB/vulnerablecode/ for support and download. + +from vulnerabilities.scraper.rust import rust_crate_advisories +from vulnerabilities.scraper.rust import load_advisory + +RUSTSEC_DB_URL = 'https://github.com/RustSec/advisory-db/archive/master.zip' + + +def test_extract_data(): + for advisory in rust_crate_advisories(RUSTSEC_DB_URL): + loaded_advisory = load_advisory(advisory) + assert len(loaded_advisory['package_name']) != 0 + assert len(loaded_advisory['vuln_id']) != 0 + assert len(loaded_advisory['advisory']) != 0 + assert len(loaded_advisory['description']) != 0 + assert len(loaded_advisory['affected_versions']) != 0 + break