Files
NexusOS/tests/test_code_run.py
T
Athena KaminskyandClaude Opus 5 affba1805c feat(chat): add run_snippet, an execution track beside the render track
render_preview validates markup and hands it to the browser, which renders it
in an opaque-origin sandboxed iframe. Nothing executes server-side. That model
fits HTML/SVG/JSX and cannot fit C, Rust or Erlang, which need a real
toolchain - so those get a second tool instead of a widened first one.

The split is the feature: the model picks a track by picking a tool, rather
than picking a `lang` value from an enum where half the entries run
server-side and half do not.

synapse/code_run.py compiles and runs one file in a throwaway directory and
returns a ```nexus-run fence carrying the source and its captured output
together, so a model cannot paste output without the code that produced it.
Backticks in the source are re-encoded as ` - still valid JSON, and it
cannot close the fence early.

It is not a sandbox, and the module docstring says so up front. What it gives
is containment by layers: consent (an action tool, gated by
action_tool_policy, per-call Approve/Deny on "ask"), static screening, a
scrubbed environment in a temp dir, wall-clock and POSIX rlimits, and a
network namespace on Linux where unprivileged userns are available. Screening
is a tripwire against a model reaching for `requests` out of habit, not a
boundary against an adversary; layers 1 and 3-5 are the load-bearing ones.

Backend RUN_LANGS and frontend run-langs.js are separate registries because
the two sides need different things - one executes, one labels - and neither
should depend on the other at runtime. tests/test_tools.py asserts the key
sets and the fence tag stay equal, so drift fails the gate instead of
rendering a run result under the wrong language.

tests/snippet_probes/ is a data catalog rather than inlined cases, so adding a
language is a data change and the meta-tests can assert every RUN_LANGS key
has both a smoke probe and a screening probe. Probes skip cleanly on hosts
without the toolchain.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 14:30:03 -05:00

309 lines
12 KiB
Python

"""The execution track: synapse/code_run.py.
Python is the only toolchain guaranteed present (it is the interpreter running
these tests), so it carries the behavioural coverage — limits, streams, exit
codes, isolation. The compiled languages are covered for the parts that hold
without their toolchain installed (screening, argv shape, the missing-toolchain
message) and skipped where they need it, so this file passes on a machine with
no clang and no rustc as well as on one with both.
"""
import shutil
import sys
import pytest
from synapse import code_run
def _requires(lang):
entry = code_run.RUN_LANGS[lang]
return pytest.mark.skipif(
not entry["tool"](), reason=f"no {lang} toolchain on this machine"
)
# ---------------------------------------------------------------------------
# Registry
# ---------------------------------------------------------------------------
def test_every_lang_has_a_complete_driver():
for name, entry in code_run.RUN_LANGS.items():
assert entry["summary"], name
assert callable(entry["tool"]), name
assert callable(entry["source_name"]), name
assert callable(entry["run"]), name
assert callable(entry["critique"]), name
assert entry["install"], name
def test_aliases_resolve_to_real_langs():
for alias, target in code_run.ALIASES.items():
assert target in code_run.RUN_LANGS, alias
assert code_run.resolve_lang("C++") == "cpp"
assert code_run.resolve_lang(" Py ") == "python"
assert code_run.resolve_lang("javascript") == "javascript" # unknown passes through
def test_erlang_source_name_follows_the_dialect():
"""escript reads the same bytes two ways depending on the extension. Writing
a bare main/1 script to main.erl makes it a module with no exports, which
fails at load with an error that says nothing about the real problem."""
assert code_run._erlang_source_name("main(_) -> ok.") == "main.escript"
assert code_run._erlang_source_name("-module(main).\nmain(_) -> ok.") == "main.erl"
def test_erlang_escript_gets_a_shebang_when_missing():
"""OTP 28+ rejects shebang-less .escript with 'Premature end of file'."""
bare = "main(_) -> ok.\n"
out = code_run._erlang_write_source(bare)
assert out.startswith("#!/usr/bin/env escript\n")
assert out.endswith(bare)
already = "#!/usr/bin/env escript\nmain(_) -> ok.\n"
assert code_run._erlang_write_source(already) == already
module = "-module(main).\n-export([main/1]).\nmain(_) -> ok.\n"
assert code_run._erlang_write_source(module) == module
# ---------------------------------------------------------------------------
# Screening
# ---------------------------------------------------------------------------
def test_clean_snippets_pass_screening():
assert code_run.critique("python", "print(sum(range(100)))") == []
assert code_run.critique("c", '#include <stdio.h>\nint main(void){puts("x");}') == []
assert code_run.critique("rust", 'fn main(){ println!("x"); }') == []
assert code_run.critique("erlang", 'main(_) -> io:format("x~n").') == []
@pytest.mark.parametrize("lang,source,needle", [
("python", "import socket\nprint(socket)", "network"),
("python", "import requests\nprint(requests)", "network"),
("python", "import subprocess\nsubprocess.run(['ls'])", "processes"),
("c", "#include <sys/socket.h>\nint main(void){return 0;}", "network"),
("c", '#include <stdlib.h>\nint main(void){system("ls");}', "processes"),
("rust", "fn main(){ std::process::Command::new(\"ls\"); }", "processes"),
("erlang", 'main(_) -> os:cmd("ls").', "processes"),
])
def test_screening_catches_the_obvious_reaches(lang, source, needle):
issues = code_run.critique(lang, source)
assert issues, f"{lang} snippet passed screening"
assert any(needle in i for i in issues), issues
def test_screening_catches_absolute_paths_and_urls():
assert any("absolute" in i for i in code_run.critique(
"python", 'data = open("/etc/passwd").read()\nprint(data)'))
# Escaped and raw Windows paths both count.
assert any("absolute" in i for i in code_run.critique(
"python", 'data = open("C:\\\\Users\\\\me").read()'))
assert any("absolute" in i for i in code_run.critique(
"python", r'data = open(r"C:\Users\me").read()'))
assert any("http" in i for i in code_run.critique(
"python", 'print("see https://example.com/data.csv")'))
def test_url_in_a_comment_is_not_a_network_reach():
"""A citation in a comment is not fetch(); bouncing it costs a useless retry."""
c = (
"/* spec: https://en.cppreference.com/w/c/string */\n"
"#include <stdio.h>\n"
"int main(void){ puts(\"ok\"); return 0; }\n"
)
assert code_run.critique("c", c) == []
def test_erlang_nproc_ceiling_is_relative_to_the_user(monkeypatch):
"""RLIMIT_NPROC is UID-scoped; an absolute 512 is not 512 of headroom."""
monkeypatch.setattr(code_run, "_user_process_count", lambda: 400)
assert code_run._max_procs_for("erlang") == 400 + code_run._ERLANG_PROC_HEADROOM
assert code_run._max_procs_for("python") == code_run._MAX_PROCS
monkeypatch.setattr(code_run, "_user_process_count", lambda: None)
assert code_run._max_procs_for("erlang") is None
def test_missing_entry_point_is_named_up_front():
"""Without this the user sees a linker error about _main, or an escript load
failure — neither of which says 'you forgot the entry point'."""
assert any("main()" in i for i in code_run.critique("c", "int add(int a){return a+1;}"))
assert any("main()" in i for i in code_run.critique("rust", "fn add(a: i32) -> i32 { a }"))
assert any("main/1" in i for i in code_run.critique("erlang", "add(A) -> A + 1."))
def test_empty_source_says_so_and_stops():
issues = code_run.critique("python", " ")
assert issues == ["source is empty or too short to run."]
def test_unknown_lang_is_refused_by_both_entry_points():
assert code_run.critique("brainfuck", "+++.")[0].startswith("cannot run")
assert code_run.run("brainfuck", "+++.")["ok"] is False
def test_oversized_source_is_refused_without_running():
issues = code_run.critique("python", "x = 1\n" * 40_000)
assert issues and "characters" in issues[0]
# ---------------------------------------------------------------------------
# Execution (python: always available)
# ---------------------------------------------------------------------------
def test_stdout_and_exit_code_come_back():
out = code_run.run("python", "print('hello', 6 * 7)")
assert out["ok"] is True
assert out["stdout"].strip() == "hello 42"
assert out["exit_code"] == 0
def test_streams_are_kept_separate():
out = code_run.run("python", "import sys\nprint('o')\nprint('e', file=sys.stderr)")
assert out["stdout"].strip() == "o"
assert out["stderr"].strip() == "e"
def test_nonzero_exit_is_still_a_successful_run():
out = code_run.run("python", "raise SystemExit(3)")
assert out["ok"] is True
assert out["exit_code"] == 3
def test_a_traceback_is_returned_not_raised():
out = code_run.run("python", "print(1/0)")
assert out["ok"] is True
assert out["exit_code"] != 0
assert "ZeroDivisionError" in out["stderr"]
def test_stdin_is_piped_in():
out = code_run.run("python", "import sys\nprint(sys.stdin.read().upper())", stdin="abc")
assert out["stdout"].strip() == "ABC"
def test_a_program_reading_stdin_with_none_given_does_not_hang():
"""stdin is always closed rather than inherited: a snippet calling input()
with nothing piped in would otherwise block on the server's own stdin until
the wall clock killed it, five seconds of 'thinking' for nothing."""
out = code_run.run("python", "print(input('prompt: '))")
assert out["ok"] is True
assert "EOFError" in out["stderr"]
def test_an_infinite_loop_is_killed_and_explained():
out = code_run.run("python", "while True:\n pass")
assert out["ok"] is False
assert out["stage"] == "run"
assert "did not finish" in out["error"]
def test_output_is_truncated_not_streamed_whole():
out = code_run.run("python", f"print('x' * {code_run.MAX_OUTPUT * 3})")
assert len(out["stdout"]) < code_run.MAX_OUTPUT + 200
assert "truncated" in out["stdout"]
def test_the_working_directory_is_ephemeral():
"""Two runs must not see each other's files. The temp dir is the only thing
standing between a snippet and the user's cwd, so its lifetime is worth a
test rather than an assumption."""
first = code_run.run("python", "open('note.txt', 'w').write('hi')\nprint('wrote')")
assert first["ok"] is True, first
second = code_run.run("python", "import os\nprint(os.path.exists('note.txt'))")
assert second["stdout"].strip() == "False"
def test_the_child_does_not_inherit_the_servers_environment():
"""A snippet has no business reading the process environment it happens to
be spawned from — that is where an API key would be."""
import os
os.environ["NEXUS_RUN_LEAK_PROBE"] = "secret"
try:
out = code_run.run(
"python", "import os\nprint(os.environ.get('NEXUS_RUN_LEAK_PROBE'))"
)
finally:
os.environ.pop("NEXUS_RUN_LEAK_PROBE", None)
assert out["stdout"].strip() == "None"
def test_home_points_at_the_scratch_dir():
"""HOME is rewritten so a snippet writing a dotfile writes it somewhere that
gets deleted, rather than into the user's real home."""
out = code_run.run("python", "import os\nprint(os.path.expanduser('~'))")
assert "nexus-run-" in out["stdout"]
# ---------------------------------------------------------------------------
# Toolchains
# ---------------------------------------------------------------------------
def test_a_missing_toolchain_explains_itself(monkeypatch):
"""The model has to be able to tell 'you cannot run this here' from 'your
code is wrong' — otherwise it rewrites a correct program repeatedly."""
monkeypatch.setitem(
code_run.RUN_LANGS["rust"], "tool", lambda: None
)
out = code_run.run("rust", 'fn main(){ println!("x"); }')
assert out["ok"] is False
assert out["stage"] == "toolchain"
assert "rustup.rs" in out["error"]
assert "Show the code instead" in out["error"]
@_requires("c")
def test_c_compiles_and_runs():
out = code_run.run("c", '#include <stdio.h>\nint main(void){printf("%d\\n", 6*7);return 0;}')
assert out["ok"] is True, out
assert out["stdout"].strip() == "42"
@_requires("c")
def test_a_compile_error_comes_back_as_a_compile_error():
"""Stage matters: the compiler's diagnostics are the useful payload, and
labelling this a run failure would hide that nothing ever executed."""
out = code_run.run("c", "int main(void){ return oops; }")
assert out["ok"] is False
assert out["stage"] == "compile"
assert "oops" in out["stderr"]
@_requires("cpp")
def test_cpp_compiles_and_runs():
out = code_run.run("cpp", '#include <iostream>\nint main(){std::cout << 6*7 << "\\n";}')
assert out["ok"] is True, out
assert out["stdout"].strip() == "42"
@_requires("rust")
def test_rust_compiles_and_runs():
out = code_run.run("rust", 'fn main(){ println!("{}", (1..=10).sum::<i32>()); }')
assert out["ok"] is True, out
assert out["stdout"].strip() == "55"
@_requires("erlang")
def test_erlang_runs_a_bare_escript():
out = code_run.run("erlang", 'main(_) -> io:format("~p~n", [lists:sum(lists:seq(1,10))]).')
assert out["ok"] is True, out
assert out["stdout"].strip() == "55"
@_requires("erlang")
def test_erlang_runs_a_module_form_script():
out = code_run.run(
"erlang",
"-module(main).\n-export([main/1]).\nmain(_) -> io:format(\"~p~n\", [7*6]).",
)
assert out["ok"] is True, out
assert out["stdout"].strip() == "42"
@pytest.mark.skipif(sys.platform != "linux", reason="unshare is Linux-only")
def test_network_isolation_probe_is_honest():
"""Either we got a namespace or we did not — but the probe must never claim
one it did not verify, because the tool description promises 'no network' on
the strength of it."""
prefix = code_run._net_isolation()
assert prefix in ([], ["unshare", "-rn"])
if prefix:
assert shutil.which("unshare")