mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-11-05 12:42:20 +01:00
fix(security): refresh client trust and publish validated SearXNG images
Repair SearXNG system and certifi stores, validate native amd64/arm64 runtime images through Compose, and publish the exact verified artifacts through a trusted CI job. Adopt released Python, certifi, grpcio, uv and Docker CLI trust fixes, with strict controls for all fourteen public incident chains. Part of #6784 and #6790. Co-authored-by: Léo <leograndcontact@gmail.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
"""Exercise removal using public X.509 certificates, without network access."""
|
||||
|
||||
import importlib.util
|
||||
import json
|
||||
import re
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
import ssl
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
SPEC = importlib.util.spec_from_file_location("searxng_repair", ROOT / "docker/searxng/repair_trust.py")
|
||||
repair = importlib.util.module_from_spec(SPEC)
|
||||
SPEC.loader.exec_module(repair)
|
||||
INCIDENT = json.loads((ROOT / "tests/fixtures/ca-trust/incident.json").read_text())
|
||||
|
||||
|
||||
class SearxngTrustTests(unittest.TestCase):
|
||||
def test_inventory_matches_all_published_fixture_ca_fingerprints(self):
|
||||
expected = set(INCIDENT["roots"]) | set(INCIDENT["intermediates"]) | set(INCIDENT["cross_signed_roots"])
|
||||
self.assertEqual(set(repair.BLOCKED), expected)
|
||||
self.assertEqual(len(expected), 21)
|
||||
for fingerprint in expected:
|
||||
self.assertEqual(hashlib.sha256(ssl.PEM_cert_to_DER_cert(INCIDENT["certificates"][fingerprint])).hexdigest(), fingerprint)
|
||||
|
||||
def test_all_known_incident_certificates_are_removed_preserving_other_certificates(self):
|
||||
unaffected = (ROOT / "tests/fixtures/ca-trust/emsign-g1.txt").read_text()
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = Path(directory) / "bundle.pem"
|
||||
for fingerprint in repair.BLOCKED:
|
||||
with self.subTest(fingerprint=fingerprint):
|
||||
path.write_text(INCIDENT["certificates"][fingerprint] + "\n" + unaffected)
|
||||
self.assertEqual(repair.filter_bundle(path), 1)
|
||||
self.assertEqual(path.read_text().strip(), unaffected.strip())
|
||||
self.assertEqual(repair.check_bundle(path), 1)
|
||||
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
context.load_verify_locations(cafile=str(path))
|
||||
self.assertEqual(len(context.get_ca_certs()), 1)
|
||||
self.assertEqual(repair.filter_bundle(path), 0)
|
||||
|
||||
def test_system_source_is_deleted_so_regeneration_cannot_restore_it(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = Path(directory) / "root.crt"
|
||||
path.write_text(INCIDENT["certificates"][next(iter(repair.BLOCKED))])
|
||||
self.assertEqual(repair.filter_bundle(path, allow_empty=True), 1)
|
||||
self.assertFalse(path.exists())
|
||||
|
||||
def test_bundle_cannot_be_emptied(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = Path(directory) / "bundle.pem"
|
||||
original = INCIDENT["certificates"][next(iter(repair.BLOCKED))]
|
||||
path.write_text(original)
|
||||
with self.assertRaisesRegex(ValueError, "refusing to empty"):
|
||||
repair.filter_bundle(path)
|
||||
self.assertEqual(path.read_text(), original)
|
||||
|
||||
def test_derived_base_matches_every_compose_pin(self):
|
||||
# The overlay corrects whatever image Compose selects; a pin bump that
|
||||
# skips the derived Dockerfile would silently run the older base.
|
||||
base = re.search(r"^FROM (\S+) AS base$", (ROOT / "docker/searxng/Dockerfile").read_text(), re.M)
|
||||
self.assertIsNotNone(base)
|
||||
for name in ("docker-compose.yml", "docker-compose.gpu-amd.yml", "docker-compose.gpu-nvidia.yml"):
|
||||
with self.subTest(compose=name):
|
||||
pins = re.findall(r"image:\s*(\S*searxng/searxng:\S+)", (ROOT / name).read_text())
|
||||
self.assertEqual(pins, [base.group(1)])
|
||||
version = base.group(1).split(":", 1)[1].split("-", 1)[0]
|
||||
overlay = (ROOT / "docker/searxng/compose.yml").read_text()
|
||||
self.assertIn(f"image: localhost/odysseus-searxng:{version}-ca-trust", overlay)
|
||||
|
||||
def test_empty_and_malformed_input_fail_closed(self):
|
||||
for text in ("", "not a certificate", "-----BEGIN CERTIFICATE-----\nbroken\n-----END CERTIFICATE-----"):
|
||||
with self.subTest(text=text), self.assertRaises((ValueError, OSError)):
|
||||
list(repair.certificates(text))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user