mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-01 02:02:20 +00:00
fix(passthrough): mask dangling private keys after escaped newlines and at the preview cut
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
7267f32954
commit
0005428a76
2 changed files with 35 additions and 1 deletions
|
|
@ -947,7 +947,9 @@ def _headers_without_body_framing(headers: httpx.Headers) -> httpx.Headers:
|
|||
)
|
||||
|
||||
|
||||
_DANGLING_PRIVATE_KEY: Final = re.compile(r"-----BEGIN[A-Z \-]*PRIVATE KEY----- ?[A-Za-z0-9+/= ]{32,}")
|
||||
_DANGLING_PRIVATE_KEY: Final = re.compile(
|
||||
r"-----BEGIN[A-Z \-]*PRIVATE KEY-----(?:[A-Za-z0-9+/= \\nr]{32,}|[A-Za-z0-9+/= \\nr]*$)"
|
||||
)
|
||||
|
||||
|
||||
def _mask_dangling_private_key(text: str) -> str:
|
||||
|
|
|
|||
|
|
@ -8482,6 +8482,38 @@ async def test_upstream_error_body_for_log_sanitizes_before_slicing():
|
|||
assert useful == sanitized[:PASSTHROUGH_UPSTREAM_ERROR_BODY_MAX_LOG_CHARS], useful[:200]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_upstream_error_body_for_log_masks_a_pem_after_a_json_escaped_newline():
|
||||
"""A PEM embedded in a JSON-escaped error string keeps literal \\n separators;
|
||||
the dangling mask must still cut it."""
|
||||
preview: Final = (
|
||||
b'{"error":"bad credentials -----BEGIN PRIVATE KEY-----\\nMIIEvQIBADANBg'
|
||||
+ b"kqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7" * 4
|
||||
+ b'\\n","status":500}'
|
||||
)
|
||||
output: Final = _upstream_error_body_for_log(preview, "utf-8", redact_secrets)
|
||||
assert "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcw" not in output, output
|
||||
assert "-----BEGIN" not in output, output
|
||||
assert "bad credentials" in output, output
|
||||
assert output.rstrip().endswith("REDACTED"), output
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_upstream_error_body_for_log_masks_a_pem_header_at_the_preview_cut():
|
||||
"""A header so close to the head cut that fewer than 32 key chars fit must
|
||||
still be masked instead of leaking the partial key."""
|
||||
prefix: Final = "x" * (PASSTHROUGH_UPSTREAM_ERROR_BODY_MAX_LOG_CHARS - len("-----BEGIN PRIVATE KEY-----") - 11)
|
||||
sanitized: Final = prefix + " -----BEGIN PRIVATE KEY----- MIIEvQIBAD" + "y" * 300
|
||||
key_start: Final = sanitized.index("MIIEvQIBAD")
|
||||
assert key_start < PASSTHROUGH_UPSTREAM_ERROR_BODY_MAX_LOG_CHARS
|
||||
assert PASSTHROUGH_UPSTREAM_ERROR_BODY_MAX_LOG_CHARS - key_start < 32
|
||||
output: Final = _upstream_error_body_for_log(sanitized.encode(), "utf-8", redact_secrets)
|
||||
head: Final = output.removesuffix(_TRUNCATION_MARKER)
|
||||
assert "-----BEGIN" not in head, head
|
||||
assert "MIIEvQIBAD" not in head, head
|
||||
assert head.rstrip().endswith("REDACTED"), head
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_upstream_error_body_for_log_marks_bodies_past_the_scan_cap():
|
||||
"""A body beyond the 64 KiB raw scan cap must carry the truncation marker
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue