Skip to content

Commit 89f0a25

Browse files
committed
fix(mcp): bound encoded audio before decode
1 parent b351dc5 commit 89f0a25

2 files changed

Lines changed: 22 additions & 0 deletions

File tree

backend/mcp_server.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,14 @@ def _read_input_audio(
240240
if not raw:
241241
return None, f"{label} is empty"
242242
return raw, None
243+
encoded = (
244+
audio_base64.split(",", 1)[-1]
245+
if audio_base64.startswith("data:")
246+
else audio_base64
247+
)
248+
max_encoded_bytes = 4 * ((_MAX_INPUT_BYTES + 2) // 3)
249+
if len(encoded) > max_encoded_bytes:
250+
return None, too_big
243251
raw = _decode_ref_audio(audio_base64)
244252
if raw is None:
245253
return None, f"{label} is not valid base64"

tests/test_mcp_output_mode.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,20 @@ def test_base64_limit_applies_to_decoded_bytes(monkeypatch):
126126
assert raw is None and err == "audio exceeds 200 MB limit"
127127

128128

129+
def test_oversized_base64_is_rejected_before_decode(monkeypatch):
130+
import mcp_server
131+
132+
monkeypatch.setattr(mcp_server, "_MAX_INPUT_BYTES", 3)
133+
134+
def fail_decode(_value): # pragma: no cover - must short-circuit first
135+
raise AssertionError("oversized base64 reached the decoder")
136+
137+
monkeypatch.setattr(mcp_server, "_decode_ref_audio", fail_decode)
138+
oversized = base64.b64encode(b"abcd").decode()
139+
raw, err = mcp_server._read_input_audio(oversized, None)
140+
assert raw is None and err == "audio exceeds 200 MB limit"
141+
142+
129143
def test_concurrent_parent_replacement_cannot_escape_base(
130144
monkeypatch, tmp_path
131145
):

0 commit comments

Comments
 (0)