Last active
December 27, 2022 07:08
-
-
Save d0now/c8d7332a9b951e68e35dfe1394394689 to your computer and use it in GitHub Desktop.
NIST SARD test case downloader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import sys | |
| import json | |
| import requests | |
| import shutil | |
| from pathlib import Path | |
| from zipfile import ZipFile | |
| API = 'https://samate.nist.gov/SARD/api/test-cases/search?flaw%5B%5D={cwe}&language%5B%5D=c&page={page}&limit={limit}' | |
| DOWNLOADS=(Path(__file__).parent / 'downloads') | |
| def download(cwe, count=-1, limit=25, os_filters=[]): | |
| response = requests.get(API.format(cwe=cwe, page=1, limit=limit)) | |
| if response.status_code != 200: | |
| raise Exception("Can't query to server.") | |
| response = json.loads(response.text) | |
| page_count = response['pageCount'] | |
| test_count = response['total'] | |
| print(f"has {test_count} results. (without os filter)") | |
| if count < 0: | |
| count = test_count | |
| for page_index in range(page_count): | |
| response = requests.get(API.format(cwe=cwe, page=page_index, limit=limit)) | |
| if response.status_code != 200: | |
| raise Exception("Can't query to server.")\ | |
| for tc in response.json()['testCases']: | |
| if len(tc['sarif']['runs']) != 1: | |
| print(f"{tc['identifiers']} has 0 or multiple sarif.runs") | |
| continue | |
| tc_sarif_runs = tc['sarif']['runs'][0] | |
| tc_props = tc_sarif_runs['properties'] | |
| tc_id: int = tc_props['id'] | |
| tc_os: str = tc_props['operatingSystem'] if 'operatingSystem' in tc_props else 'any' | |
| tc_download: str = tc['download'] | |
| filtered = False | |
| for filt in os_filters: | |
| if filt in tc_os: | |
| filtered = True | |
| if filtered: | |
| continue | |
| tc_download_zip_path = DOWNLOADS / f"{tc_id}.zip" | |
| tc_download_dir_path = DOWNLOADS / f"{tc_id}" | |
| print(f"downloading {tc_id} to {tc_download_zip_path}") | |
| response = requests.get(tc_download) | |
| if response.status_code != 200: | |
| print(f"failed to download {tc_id}") | |
| continue | |
| tc_download_zip_path.write_bytes(response.content) | |
| print(f"unarchiving {tc_download_zip_path} to {tc_download_dir_path}") | |
| if tc_download_dir_path.is_dir(): | |
| print(f"{tc_download_dir_path} has content. removing...") | |
| shutil.rmtree(tc_download_dir_path) | |
| tc_download_dir_path.mkdir(exist_ok=True) | |
| with ZipFile(tc_download_zip_path) as zipfile: | |
| zipfile.extractall(tc_download_dir_path) | |
| print(f"unlinking {tc_download_zip_path}") | |
| tc_download_zip_path.unlink(missing_ok=True) | |
| count -= 1 | |
| if count <= 0: | |
| return | |
| def main(args): | |
| if args.os_filters: | |
| os_filters = args.os_filters.split(';') | |
| else: | |
| os_filters = [] | |
| download(args.cwe, args.download_count, args.download_limit, os_filters) | |
| if __name__ == '__main__': | |
| import argparse | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument('--cwe', required=True) | |
| parser.add_argument('--download-count', default=100, type=int) | |
| parser.add_argument('--download-limit', default=100 ,type=int) | |
| parser.add_argument('--os-filters', default='windows;macos') | |
| args = parser.parse_args() | |
| if not DOWNLOADS.is_dir(): | |
| DOWNLOADS.mkdir(exist_ok=True) | |
| ec = main(args) | |
| sys.exit(ec) |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can just build all test cases by running follow command on
downloadsdirectory: