Initial RPCScope release

This commit is contained in:
0x000 committed 2026-10-15 12:34:26 -04:00
commit 9dc7289652
40 files changed
+6688

No files matched your search

+147
View File
@@ -0,0 +1,147 @@
"""Advisory refresh is metadata-only, bounded, and atomic; no network needed."""
import copy
import json
import tempfile
import unittest
from pathlib import Path
from unittest.mock import patch
from rpcscope.advisories import ADVISORIES, _download, sync_advisories
from rpcscope.catalog import CHECKS
MICROSOFT = "f38d906d-7342-40ea-92c1-6c4a2c6478c8"
def record_for(advisory):
return {
"dataType": "CVE_RECORD",
"cveMetadata": {
"cveId": advisory.key, "state": "PUBLISHED", "assignerOrgId": MICROSOFT,
"datePublished": "2026-05-12T16:58:50.091Z", "dateUpdated": "2026-08-10T15:12:59.779Z",
},
"containers": {"cna": {
"title": "Vendor advisory title",
"providerMetadata": {"orgId": MICROSOFT, "shortName": "microsoft"},
"references": [
{"url": advisory.reference}, {"url": "https://example.com/poc.py"},
{"url": "https://msrc.microsoft.com.evil.example/metadata"},
],
"affected": [{"vendor": "Microsoft", "product": "Windows Example",
"platforms": ["x64-based Systems"],
"versions": [{"version": "10.0.0", "lessThan": "10.0.1",
"versionType": "custom", "status": "affected"}]}],
"untrusted_command": "do not carry executable fields into cache",
}},
}
class AdvisoryTests(unittest.TestCase):
def test_registry_remains_separate_from_executable_checks(self):
self.assertEqual(len(ADVISORIES), 7)
self.assertTrue(all(item.status == "review-only" for item in ADVISORIES.values()))
executable_cves = {cve for check in CHECKS.values() if check.kind == "vulnerability" for cve in check.cves}
self.assertFalse(executable_cves.intersection(ADVISORIES))
self.assertEqual(CHECKS["longlogon"].kind, "precondition")
self.assertEqual(CHECKS["longlogon"].positive_status, "precondition-met")
self.assertIn("/2020/1xxx/", ADVISORIES["CVE-2020-1206"].cna_url)
self.assertIn("/2026/41xxx/", ADVISORIES["CVE-2026-41089"].cna_url)
def test_sync_copies_selected_metadata_and_never_fetches_references(self):
fetched = []
by_url = {item.cna_url: item for item in ADVISORIES.values()}
def fetch(url):
fetched.append(url)
return json.dumps(record_for(by_url[url])).encode()
with tempfile.TemporaryDirectory() as temporary:
path = Path(temporary) / "nested" / "advisories.json"
result = sync_advisories(path, fetch=fetch)
dataset = json.loads(path.read_text(encoding="utf-8"))
self.assertEqual(fetched, list(by_url))
self.assertEqual(dataset["advisories"], result)
self.assertFalse(dataset["scanner_coverage"])
self.assertEqual(result[0]["title"], "Vendor advisory title")
self.assertEqual(result[0]["vendorReferences"], [result[0]["reference"]])
self.assertEqual(result[0]["affected"][0]["versions"][0]["lessThan"], "10.0.1")
self.assertNotIn("untrusted_command", json.dumps(result))
self.assertTrue(all(item["status"] == "review-only" for item in result))
def test_invalid_later_record_preserves_existing_destination(self):
advisories = list(ADVISORIES.values())
index = 0
def fetch(url):
nonlocal index
record = record_for(advisories[index])
index += 1
if index == 2:
record["cveMetadata"]["cveId"] = "CVE-2000-0001"
return json.dumps(record).encode()
with tempfile.TemporaryDirectory() as temporary:
path = Path(temporary) / "advisories.json"
path.write_text("existing valid cache", encoding="utf-8")
with self.assertRaisesRegex(ValueError, "CVE ID mismatch"):
sync_advisories(path, fetch=fetch)
self.assertEqual(path.read_text(encoding="utf-8"), "existing valid cache")
def test_unpublished_untrusted_and_malformed_records_fail_closed(self):
advisory = next(iter(ADVISORIES.values()))
original = record_for(advisory)
cases = []
for mutate in (
lambda record: record["cveMetadata"].update(state="REJECTED"),
lambda record: record["cveMetadata"].update(assignerOrgId="other"),
lambda record: record["containers"]["cna"]["providerMetadata"].update(orgId="other"),
lambda record: record["containers"]["cna"]["providerMetadata"].update(shortName="other"),
lambda record: record["containers"]["cna"].update(title="bad\x1b[31m"),
lambda record: record["cveMetadata"].update(dateUpdated="yesterday"),
lambda record: record["containers"]["cna"].update(references=[]),
lambda record: record["containers"]["cna"].update(affected=[{}] * 513),
):
record = copy.deepcopy(original)
mutate(record)
cases.append(json.dumps(record).encode())
cases.extend([b"not JSON", b"{}", b"x" * (2 * 1024 * 1024 + 1)])
with tempfile.TemporaryDirectory() as temporary:
for payload in cases:
with self.subTest(payload_size=len(payload)):
path = Path(temporary) / "advisories.json"
with self.assertRaises(ValueError):
sync_advisories(path, fetch=lambda url: payload)
self.assertFalse(path.exists())
def test_absent_cna_title_has_curated_fallback(self):
by_url = {item.cna_url: item for item in ADVISORIES.values()}
def fetch(url):
record = record_for(by_url[url])
del record["containers"]["cna"]["title"]
return json.dumps(record).encode()
with tempfile.TemporaryDirectory() as temporary:
snapshots = sync_advisories(Path(temporary) / "metadata.json", fetch=fetch)
self.assertEqual(snapshots[0]["title"], next(iter(ADVISORIES.values())).title)
def test_network_failure_preserves_existing_destination(self):
def fetch(url):
raise OSError("network unavailable")
with tempfile.TemporaryDirectory() as temporary:
path = Path(temporary) / "metadata.json"
path.write_text("old cache", encoding="utf-8")
with self.assertRaisesRegex(ValueError, "network unavailable"):
sync_advisories(path, fetch=fetch)
self.assertEqual(path.read_text(encoding="utf-8"), "old cache")
def test_downloader_bounds_read_and_timeout_and_rejects_redirect(self):
url = next(iter(ADVISORIES.values())).cna_url
with patch("rpcscope.advisories.urlopen") as opening:
response = opening.return_value.__enter__.return_value
response.geturl.return_value = url
response.read.return_value = b"{}"
self.assertEqual(_download(url), b"{}")
self.assertEqual(opening.call_args.kwargs["timeout"], 15)
response.read.assert_called_once_with(2 * 1024 * 1024 + 1)
response.geturl.return_value = "https://example.com/redirect"
with self.assertRaisesRegex(ValueError, "redirected"):
_download(url)
if __name__ == "__main__":
unittest.main()