Fix quadratic ReDoS in PEM import block scanning
Replace the backtracking _PEM_BLOCK regex with a forward-only scanner that indexes END markers by label, so repeated unterminated headers do not cause the regex to rescan the remaining input. Impact: 80 KiB payload went from 8.34 s to 0.001 s.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""Core domain tests: names, extensions, keys, certificates, CRLs and exports."""
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
import unittest
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
@@ -273,6 +274,30 @@ class ExportImportTest(unittest.TestCase):
|
||||
items = imports.parse_file(pem.data, "export.crt")
|
||||
self.assertEqual(items[0].kind, "certificate")
|
||||
|
||||
def test_pem_bundle_ignores_incomplete_blocks(self) -> None:
|
||||
certificate = exports.export_certificate(self.cert, "pem", name="export").data
|
||||
private_key = keys.private_pem(self.key)
|
||||
pem = (
|
||||
b"before\n-----BEGIN INCOMPLETE-----\nignored\n"
|
||||
+ certificate
|
||||
+ b"\n"
|
||||
+ private_key
|
||||
+ b"\nafter\n"
|
||||
)
|
||||
items = imports.parse_pem_bundle(pem)
|
||||
self.assertEqual([item.kind for item in items], ["certificate", "key"])
|
||||
mismatched = b"-----BEGIN CERTIFICATE-----\nignored\n-----END PRIVATE KEY-----"
|
||||
self.assertEqual(imports.parse_pem_bundle(mismatched), [])
|
||||
|
||||
def test_unterminated_pem_headers_complete_quickly(self) -> None:
|
||||
header = b"-----BEGIN UNTERMINATED-----\n"
|
||||
data = header * ((80 * 1024) // len(header))
|
||||
started = time.perf_counter()
|
||||
items = imports.parse_pem_bundle(data)
|
||||
elapsed = time.perf_counter() - started
|
||||
self.assertEqual(items, [])
|
||||
self.assertLess(elapsed, 2.0, f"PEM scanning took {elapsed:.3f}s for {len(data)} bytes")
|
||||
|
||||
def test_key_exports(self) -> None:
|
||||
for fmt in ("pem-public", "pem-private", "pkcs8", "ssh-public", "jwk-public", "pvk"):
|
||||
result = exports.export_key(self.key, fmt, name="export")
|
||||
|
||||
Reference in New Issue
Block a user