Skip to content
8 changes: 8 additions & 0 deletions deploy/tests/journeys/backends/fleet.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,14 @@ def _curl(self, method: str, path: str, body: Optional[dict] = None) -> tuple[in
if body is not None:
args += ["-H", "content-type: application/json", "-d", json.dumps(body)]
try:
# `self._base` comes from the stand's own env (the operator who
# launched pytest), and reaches curl as a single argv element — no
# shell, no string-assembled command. The one sharp edge is a value
# beginning with `-`, which curl would read as an option rather than
# a URL; that is a misconfiguration by the person who set it, not a
# boundary crossing. It would NOT be acceptable for a value arriving
# from CI metadata or any source outside this trust domain.
# nosemgrep: python.lang.security.audit.dangerous-subprocess-use-tainted-env-args.dangerous-subprocess-use-tainted-env-args
proc = subprocess.run(args, capture_output=True, timeout=_HTTP_TIMEOUT_S + 5)
except subprocess.SubprocessError as exc:
raise BackendUnavailable(f"fleet wire failure on {path}: {exc}") from exc
Expand Down
9 changes: 9 additions & 0 deletions deploy/tests/journeys/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,15 @@ def _fleet_exec(argv: list[str], timeout: float):
if not limactl:
raise OSError("limactl not found for FLEET_LIMA_INSTANCE")
argv = [limactl, "shell", os.environ["FLEET_LIMA_INSTANCE"], "--", *argv]
# FLEET_LIMA_INSTANCE is operator-supplied stand configuration, set by whoever
# already owns the Lima VM this shells into — same trust domain, no privilege
# boundary crossed. Worth stating the sharp edge rather than hiding it: the
# `limactl shell ... -- argv` leg rides ssh semantics, which JOIN argv into a
# command line the VM's shell re-parses, so metacharacters in that value would
# execute there. That is a real mechanism; it is acceptable only because the
# value's author already has shell on that VM. It would NOT be acceptable for
# a value reaching this from CI metadata or any untrusted source.
# nosemgrep: python.lang.security.audit.dangerous-subprocess-use-tainted-env-args.dangerous-subprocess-use-tainted-env-args
return subprocess.run(argv, capture_output=True, text=True, timeout=timeout)


Expand Down
27 changes: 27 additions & 0 deletions deploy/tests/journeys/test_e_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,12 @@ def _operator_sock_reachable() -> bool:
POST uses. Never raises; a missing sudo/curl surfaces as False -> loud skip.
"""
try:
# `_OPERATOR_SOCK` is a module constant and `_sudo_prefix()` returns
# either [] or ["sudo"]; the only env-derived part is whether sudo is
# used at all, decided by the operator running the suite on their own
# host. List argv, no shell.
probe = subprocess.run(
# nosemgrep: python.lang.security.audit.dangerous-subprocess-use-tainted-env-args.dangerous-subprocess-use-tainted-env-args
_sudo_prefix() + ["test", "-S", _OPERATOR_SOCK],
capture_output=True,
timeout=10,
Expand Down Expand Up @@ -175,7 +180,14 @@ def _psql(sql: str) -> Optional[str]:
if not docker:
return None
try:
# `sql` comes from this file only: literals, plus one f-string whose
# interpolations are `int(value)` and a module constant. `_CONTROL_DB`,
# `_DB_USER` and `_DB_NAME` are stand config from the operator's env.
# Each reaches psql as one argv element — `docker exec` execs directly
# rather than through /bin/sh — so nothing is re-parsed. Would NOT hold
# if `sql` were ever built from a fixture the caller controls.
proc = subprocess.run(
# nosemgrep: python.lang.security.audit.dangerous-subprocess-use-tainted-env-args.dangerous-subprocess-use-tainted-env-args
[
docker, "exec", _CONTROL_DB,
"psql", "-U", _DB_USER, "-d", _DB_NAME, "-t", "-A", "-c", sql,
Expand Down Expand Up @@ -238,6 +250,10 @@ def _operator_post(path: str) -> int:
)
try:
proc = subprocess.run(
# `curl`, `_OPERATOR_SOCK` and the URL path are harness constants;
# `_sudo_prefix()` returns [] or ["sudo"]. curl receives the socket path as
# one argv element with no shell in between.
# nosemgrep: python.lang.security.audit.dangerous-subprocess-use-tainted-env-args.dangerous-subprocess-use-tainted-env-args
_sudo_prefix() + [
curl, "-sS", "--max-time", "15",
"--unix-socket", _OPERATOR_SOCK,
Expand All @@ -262,6 +278,10 @@ def _control_container_id(docker: str) -> Optional[str]:
"""Resolve the running control container by its compose service label."""
try:
proc = subprocess.run(
# `docker` is the resolved binary and `_CONTROL_SERVICE` is stand config from
# the operator's own env, passed as one argv element to a `--filter` flag.
# No shell parses it.
# nosemgrep: python.lang.security.audit.dangerous-subprocess-use-tainted-env-args.dangerous-subprocess-use-tainted-env-args
[
docker, "ps", "--filter",
f"label=com.docker.compose.service={_CONTROL_SERVICE}",
Expand Down Expand Up @@ -699,6 +719,10 @@ def test_e6_rowless_container_killed_valid_row_survives(backend: Backend, expect
stray_key = f"stray-{int(time.time() * 1000)}"
stray_name = f"ocu-sess-{stray_key}"
run = subprocess.run(
# `docker` and `stray_name` are harness-controlled: the name is built from a
# literal prefix in this file. Stand config (`_SESSION_IMAGE`) is a single
# argv element that docker execs directly, never through /bin/sh.
# nosemgrep: python.lang.security.audit.dangerous-subprocess-use-tainted-env-args.dangerous-subprocess-use-tainted-env-args
[
docker, "run", "-d", "--name", stray_name,
"--label", "ocu-session=true",
Expand Down Expand Up @@ -744,6 +768,9 @@ def test_e6_rowless_container_killed_valid_row_survives(backend: Backend, expect
)
finally:
# Clean up the stray if it somehow survived (so a re-run is idempotent).
# `docker` is the resolved binary path and `stray_cid` is a container id this
# test itself created moments earlier. List argv, no shell.
# nosemgrep: python.lang.security.audit.dangerous-subprocess-use-tainted-env-args.dangerous-subprocess-use-tainted-env-args
subprocess.run([docker, "rm", "-f", stray_cid], capture_output=True, timeout=30)


Expand Down
7 changes: 7 additions & 0 deletions deploy/tests/journeys/test_k_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ def _curl(
if body is not None:
args += ["-H", "content-type: application/json", "-d", body]
try:
# `args` is assembled above from literals, `ADMIN_URL` and the operator
# credentials (all stand config from the operator's own env), plus this
# function's parameters — `body` carries the env-derived credentials via
# `_login`, so this is env-sourced data, not literals. It is safe because
# curl gets each value as ONE argv element with no shell in between, not
# because the values are constants.
# nosemgrep: python.lang.security.audit.dangerous-subprocess-use-tainted-env-args.dangerous-subprocess-use-tainted-env-args
proc = subprocess.run(args, capture_output=True, text=True, timeout=timeout + 5)
except subprocess.SubprocessError as exc:
raise RuntimeError(f"curl transport failure on {path}: {exc}") from exc
Expand Down
Loading
Loading