Skip to content

Commit 728bba2

Browse files
authored
fail on 404 if date > 2026-06-11 #352 (#353)
1 parent ca439a6 commit 728bba2

3 files changed

Lines changed: 59 additions & 2 deletions

File tree

tests/full/other_tests/test_tasks.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from datetime import date
12
from unittest.mock import patch, Mock
23
from io import BytesIO
34
import time
@@ -210,6 +211,19 @@ def test_download_file_retries_on_download_timeout(mock_read_into, mock_path, mo
210211
# Should have been called 3 times (2 failures + 1 success)
211212
assert mock_read_into.call_count == 3
212213

214+
@patch('vulmatch.worker.tasks.requests.get')
215+
@patch('vulmatch.worker.tasks.read_into')
216+
def test_download_file_handles_empty_bundle_correctly(mock_read_into, mock_get, job, tmp_path, eager_celery):
217+
mock_read_into.return_value = 2
218+
tempdir = str(tmp_path)
219+
mock_response = Mock()
220+
mock_response.status_code = 200
221+
mock_response.url = 'https://example.com/file.json'
222+
mock_get.return_value = mock_response
223+
result = tasks.download_file.delay('https://example.com/file.json', tempdir, job_id=job.id)
224+
assert result.get() == ""
225+
226+
213227

214228
@patch('vulmatch.worker.tasks.requests.get')
215229
def test_download_file_max_retries_exceeded(mock_get, job, tmp_path, eager_celery):
@@ -231,3 +245,35 @@ def test_download_file_max_retries_exceeded(mock_get, job, tmp_path, eager_celer
231245
assert 'after 3 retries' in job.errors[0]
232246
assert 'Network error' in job.errors[0]
233247

248+
249+
@pytest.mark.parametrize(
250+
"d,should_fail",
251+
[
252+
(date(2027, 1, 1), True),
253+
(date(2025, 1, 1), False),
254+
(date(2026, 10, 11), True),
255+
(date(2026, 6, 10), False),
256+
]
257+
)
258+
@patch('vulmatch.worker.tasks.requests.get')
259+
def test_download_file__fails_on_404(mock_get, job, tmp_path, d, should_fail, eager_celery):
260+
"""Test download_file fails after max retries"""
261+
from requests.models import Response
262+
r = Response()
263+
r.status_code = 404
264+
mock_get.return_value = r
265+
tempdir = str(tmp_path)
266+
267+
# with pytest.raises(requests.exceptions.RequestException):
268+
r = tasks.download_file.delay('https://example.com/file.json', tempdir, job_id=job.id, file_date=d)
269+
270+
# Should have been called 4 times (1 initial + 3 retries as per max_retries=3)
271+
assert mock_get.call_count == 1
272+
assert r.failed() == should_fail
273+
274+
job.refresh_from_db()
275+
assert len(job.errors) == 1
276+
if should_fail:
277+
assert "file does not exist on remote server: https://example.com/file.json" in job.errors[0]
278+
279+

utilities/s2a_importer/insert_archive_cve.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ def create_directory(path):
7070
def download_file(url, destination):
7171
response = requests.get(url)
7272
if response.status_code == 200:
73+
if response.content == "{}":
74+
print(f"No STIX objects created for date")
75+
return True
7376
with open(destination, 'wb') as file:
7477
file.write(response.content)
7578
print(f"Downloaded file: {destination}")

vulmatch/worker/tasks.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def run_nvd_task(data, job: Job, nvd_type='cve'):
6969
tasks = []
7070
for d in dates:
7171
url = urljoin(settings.CVE2STIX_BUCKET_ROOT_PATH, daily_url(d, nvd_type))
72-
task = download_file.si(url, temp_dir, job_id=job.id)
72+
task = download_file.si(url, temp_dir, job_id=job.id, file_date=d)
7373
task |= upload_file.s(f'nvd_{nvd_type}', stix2arango_note=f"vulmatch-{nvd_type}-date={d.strftime('%Y-%m-%d')}", job_id=job.id, params=job.parameters)
7474
task.set_immutable(True)
7575
tasks.append(task)
@@ -145,8 +145,11 @@ def read_into(streamed_resp: requests.Response, fp, chunk_size=1024*1024, read_t
145145
raise DownloadTimeoutError(downloaded, total)
146146
return downloaded
147147

148+
class MissingFileError(Exception):
149+
pass
150+
148151
@app.task(bind=True, base=CustomTask, max_retries=3, default_retry_delay=5, autoretry_for=(requests.exceptions.RequestException, DownloadTimeoutError))
149-
def download_file(self, urlpath, tempdir, job_id=None):
152+
def download_file(self, urlpath, tempdir, job_id=None, file_date: date=None):
150153
Path(tempdir).mkdir(parents=True, exist_ok=True)
151154
logging.info('downloading bundle at `%s`', urlpath)
152155
job = Job.objects.get(pk=job_id)
@@ -159,9 +162,14 @@ def download_file(self, urlpath, tempdir, job_id=None):
159162
filename = Path(tempdir)/resp.url.split('/')[-1]
160163
with filename.open('wb') as f:
161164
total_bytes = read_into(resp, f, read_timeout=settings.DOWNLOAD_TIMEOUT_SECONDS)
165+
if total_bytes == 2: # see https://github.com/muchdogesec/cve2stix/issues/128 [body is {}]
166+
logging.info("found an empty bundle, skipping...")
167+
return ""
162168
logging.info(f'downloaded {total_bytes} bytes into {filename}')
163169
return str(filename)
164170
elif resp.status_code == 404:
171+
if file_date and file_date > date(2026, 6, 11): # see https://github.com/muchdogesec/vulmatch/issues/352
172+
raise MissingFileError(f"file does not exist on remote server: {urlpath}")
165173
job.errors.append(f'{resp.url} not found')
166174
else:
167175
job.errors.append(f'{resp.url} failed with status code: {resp.status_code}')

0 commit comments

Comments
 (0)