2026-08-17 06:36:24 -03:00

55 lines
1.7 KiB
Python

#!/usr/bin/env python3
"""Bounded-memory stream helpers for the Hermes SCM broker."""
from __future__ import annotations
import tempfile
import time
from typing import BinaryIO
from gitea_api_policy import PolicyError
def spool_response(
response,
maximum: int,
forbidden: tuple[bytes, ...],
*,
memory_limit: int,
chunk_size: int,
deadline_seconds: float,
) -> tuple[BinaryIO, int]:
"""Spool an upstream response to disk while scanning chunk boundaries."""
spool = tempfile.SpooledTemporaryFile(max_size=memory_limit, dir="/tmp")
carry = b""
total = 0
deadline = time.monotonic() + deadline_seconds
try:
while True:
remaining = deadline - time.monotonic()
if remaining <= 0:
raise PolicyError("SCM upstream response deadline exceeded")
raw = getattr(getattr(response, "fp", None), "raw", None)
sock = getattr(raw, "_sock", raw)
if hasattr(sock, "settimeout"):
sock.settimeout(remaining)
chunk = response.read(chunk_size)
if not chunk:
break
total += len(chunk)
if total > maximum:
raise PolicyError("SCM upstream response exceeds the safe size limit")
candidate = carry + chunk
if any(value in candidate for value in forbidden):
raise PolicyError(
"Git upstream response contains runtime credential material"
)
width = max(len(value) for value in forbidden) - 1
carry = candidate[-width:] if width else b""
spool.write(chunk)
spool.seek(0)
return spool, total
except Exception:
spool.close()
raise