Skip to content

Instantly share code, notes, and snippets.

@d0now
Last active December 27, 2022 07:08
Show Gist options
  • Select an option

  • Save d0now/c8d7332a9b951e68e35dfe1394394689 to your computer and use it in GitHub Desktop.

Select an option

Save d0now/c8d7332a9b951e68e35dfe1394394689 to your computer and use it in GitHub Desktop.
NIST SARD test case downloader
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)
@d0now
Copy link
Author

d0now commented Dec 27, 2022

You can just build all test cases by running follow command on downloads directory:

find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "make -C {} build" \;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment