security: Sandbox verbirgt API-Schlüssel und Home-Verzeichnis

Erzeugter Code las über pandas.io.common.os – ohne import os, an validate_imports
vorbei – den OPENROUTER_API_KEY und das gesamte Home-Verzeichnis (nachgewiesen).
Kein Netz, aber alles Gedruckte landet in Ergebnis-JSON und Report. In gespeicherten
Ergebnissen fand sich kein Schlüssel.

- Umgebung des Programms ist eine Positivliste (solver_env), auch bei SOLVER_SANDBOX=aus
- bubblewrap verdeckt das Home per --tmpfs; nur sys.prefix/sys.base_prefix wieder lesbar

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-09-18 13:23:53 +02:00
commit 8dd5073cd1

View file

@ -832,3 +832,41 @@ def test_unprotected_run_carries_the_warning_into_the_result(monkeypatch):
code = 'def main():\n """Test."""\n report("optimal", 1.0, {})\n\n\nif __name__ == "__main__":\n main()\n'
run = solver_stage._check_and_run(code, 30, make_spec())
assert any("Sandbox abgeschaltet" in w for w in run.warnings)
# Liest Umgebung und Home-Verzeichnis ohne `import os` – über ein Attribut von pandas, das
# validate_imports nicht sieht. Nachgewiesen: vorher waren API-Schlüssel und ~ vollständig lesbar.
PEEK_CODE = '''
import pandas as pd
def main():
"""Späht Umgebung und Home-Verzeichnis aus."""
_os = pd.io.common.os
try:
eintraege = len(_os.listdir({home!r}))
except OSError:
eintraege = -1
report("optimal", 0.0, {{"schluessel": len(_os.environ.get("OPENROUTER_API_KEY", "")),
"home_eintraege": eintraege}})
if __name__ == "__main__":
main()
'''
def test_program_does_not_see_api_keys(monkeypatch):
monkeypatch.setenv("OPENROUTER_API_KEY", "sk-geheim")
run = run_solver_code(PEEK_CODE.format(home="/"))
assert run.status == SolverStatus.OPTIMAL, run.error
assert run.solution["schluessel"] == 0
@pytest.mark.skipif(not shutil.which("bwrap"), reason="bubblewrap nicht installiert")
def test_sandbox_hides_the_home_directory():
from pathlib import Path
run = run_solver_code(PEEK_CODE.format(home=str(Path.home())))
assert run.status == SolverStatus.OPTIMAL, run.error
# Sichtbar bleiben höchstens die Einhängepunkte der Python-Installationen (.venv, Basis-Python)
assert run.solution["home_eintraege"] <= 2