Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 62 additions & 56 deletions vulnerabilities/scraper/rust.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
38 changes: 38 additions & 0 deletions vulnerabilities/tests/test_rust.py
Original file line number Diff line number Diff line change
@@ -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