Harden sandbox: exec namespace-dict aliases, bare-host + client-instance network calls, shuf/uniq writers, docstring guard splice

Close five gaps Codex found on the round-58 branch (four inline P1 plus one
review-body P1).

- exec/eval namespace-dict aliases: the outward-reference model for an exec /
  eval payload only collected ast.Name loads, so a constant-key namespace lookup
  (exec("globals()['f']('...')"), and the locals() / vars() forms) referenced the
  caller's f = os.system without a Name node and slipped past the alias check.
  Treat a literal key of a bare globals() / locals() / vars() subscript as a free
  outward reference so the caller-alias resolution runs on it.

- bare-host network APIs: http.client.HTTPConnection / HTTPSConnection and the
  socket name-resolution helpers (getaddrinfo, gethostbyname, gethostbyname_ex)
  take a HOST, not a URL, so their literal first arg (or host= keyword) was parsed
  as a scheme://host URL, found no scheme, and was never checked. Check the literal
  directly against the metadata denylist / allowlist for these callees, and add the
  forward name-resolution helpers to the scanned set.

- client-instance network calls: a request chained off a client constructor
  (requests.Session().get(url), httpx.Client().get(url), build_opener().open(url),
  or s.get(url) where s was bound to such a constructor) has a fully-qualified name
  of just the method, so it never matched a module-rooted network prefix and the
  host went unchecked. Match these by the receiver being a client-ctor call or a
  same-name single-assignment alias, extract the host (arg1 for .request), and run
  the same host check. A .get / .open on a plain dict or file receiver is excluded.

- shuf / uniq output writers: shuf -o / --output and a uniq second (output) operand
  write outside the workdir in an unguarded child that the realpath backstop cannot
  see, so they are blocked like the existing sort -o full-block. uniq skip-field /
  skip-char counts are not treated as output operands.

- module docstring under the guard splice: a leading string literal is the module
  docstring only while it is the first statement, so prepending the runtime guard
  ahead of it made __doc__ None. Splice the guard after a leading docstring (as is
  already done for future imports) so the docstring stays first; a same-line
  "\"\"\"doc\"\"\"; write" tail still moves after the guard and is confined.

Regression coverage: TestRound59Bypasses in tests/test_sandbox_tools.py (exec /
eval namespace-dict aliases, bare-host metadata / allowlist checks, client-instance
and aliased-instance request calls, shuf / uniq output writers, plus a round59
benign-allowed set: trusted-host requests / sessions / HTTPConnection / getaddrinfo,
dict.get and file .open, a benign exec payload, and shuf / uniq without an output
operand) and, in tests/test_sandbox_runtime_backstop.py, a module-docstring-preserved
case and a docstring same-line write-escape denial.
This commit is contained in:
danielhanchen 2026-07-11 03:46:40 +00:00
commit 7e15a8bca9
3 changed files with 395 additions and 99 deletions

View file

@ -2537,6 +2537,7 @@ def _find_blocked_commands(command: str) -> set[str]:
"ssed",
"perl",
"sort",
"shuf",
"find",
"dd",
"tee",
@ -2597,6 +2598,12 @@ def _find_blocked_commands(command: str) -> set[str]:
if al.startswith("--output") or (_short and "o" in al[1:]):
blocked.add("mutating:sort")
break
elif _base == "shuf":
# shuf -o FILE / --output=FILE writes its shuffled output to FILE in an unguarded
# child, escaping the workdir just like sort -o.
if al.startswith("--output") or (_short and "o" in al[1:]):
blocked.add("mutating:shuf")
break
elif _base == "find":
# -delete removes; -fprint/-fprintf/-fprint0 and -fls write their listing to a
# named FILE (find . -fls /tmp/escape truncates/creates it in an unguarded child).
@ -2619,6 +2626,31 @@ def _find_blocked_commands(command: str) -> set[str]:
blocked.add("mutating:history")
break
# uniq [OPTION]... [INPUT [OUTPUT]] writes to its SECOND positional operand (uniq in out /
# uniq /dev/null /tmp/p) in an unguarded child -- a native writer no redirect token exposes,
# like sort -o. Block when a second bare operand is present; a single INPUT (or none) reads
# to stdout and stays allowed. -f / -s / -w take a separated numeric value, so skip it.
for i in _cmd_word_idx:
if _token_basename(tokens[i]) != "uniq":
continue
_uniq_ops = 0
_skip_val = False
for k in range(i + 1, len(tokens)):
a = tokens[k]
if a in _SHELL_SEPARATORS or a in _SHELL_KEYWORDS_AS_SEP:
break
if _skip_val:
_skip_val = False
continue
if a.startswith("-") and a != "-":
if a in ("-f", "-s", "-w", "--skip-fields", "--skip-chars", "--check-chars"):
_skip_val = True # separated numeric value belongs to the flag, not an operand
continue
_uniq_ops += 1
if _uniq_ops == 2: # the OUTPUT operand
blocked.add("mutating:uniq")
break
return blocked
@ -6813,32 +6845,48 @@ def _payload_outward_load_names(src, mode):
return set()
# eval: a single expression with no bindings -- every loaded name resolves outward.
if isinstance(inner, ast.Expression):
return {
names = {
_n.id
for _n in ast.walk(inner)
if isinstance(_n, ast.Name) and isinstance(_n.ctx, ast.Load)
}
names, module_bound = _module_toplevel_free_loads(inner)
try:
import symtable as _symtable
_stack = list(_symtable.symtable(src, "<payload>", "exec").get_children())
while _stack:
_s = _stack.pop()
for _sym in _s.get_symbols():
# A nested-scope reference that is free / global resolves to the module (caller)
# scope UNLESS the payload binds it at module top level (then the payload controls
# it, and any payload-local sink is caught by the inner scan).
if (
_sym.is_referenced()
and (_sym.is_free() or _sym.is_global())
and _sym.get_name() not in module_bound
):
names.add(_sym.get_name())
_stack.extend(_s.get_children())
except Exception: # pragma: no cover - defensive: fail closed by flagging every load
for _n in ast.walk(inner):
if isinstance(_n, ast.Name) and isinstance(_n.ctx, ast.Load):
names.add(_n.id)
else:
names, module_bound = _module_toplevel_free_loads(inner)
try:
import symtable as _symtable
_stack = list(_symtable.symtable(src, "<payload>", "exec").get_children())
while _stack:
_s = _stack.pop()
for _sym in _s.get_symbols():
# A nested-scope reference that is free / global resolves to the module (caller)
# scope UNLESS the payload binds it at module top level (then the payload
# controls it, and any payload-local sink is caught by the inner scan).
if (
_sym.is_referenced()
and (_sym.is_free() or _sym.is_global())
and _sym.get_name() not in module_bound
):
names.add(_sym.get_name())
_stack.extend(_s.get_children())
except Exception: # pragma: no cover - defensive: fail closed by flagging every load
for _n in ast.walk(inner):
if isinstance(_n, ast.Name) and isinstance(_n.ctx, ast.Load):
names.add(_n.id)
# A constant-key namespace-dict lookup (globals()['f'] / locals()['f'] / vars()['f']) reads a
# name from the caller's namespace WITHOUT a Name node, so its key is an outward reference too:
# exec("globals()['f']('rm -rf /')") reaches the caller's f = os.system. Add the literal keys.
for _n in ast.walk(inner):
if (
isinstance(_n, ast.Subscript)
and isinstance(_n.value, ast.Call)
and isinstance(_n.value.func, ast.Name)
and _n.value.func.id in ("globals", "locals", "vars")
and not _n.value.args
and not _n.value.keywords
):
_key = _n.slice
if isinstance(_key, ast.Constant) and isinstance(_key.value, str):
names.add(_key.value)
return names
@ -10003,6 +10051,8 @@ def _check_signal_escape_patterns(
"requests.Session",
"http.client.HTTPConnection",
"http.client.HTTPSConnection",
"socket.gethostbyname",
"socket.gethostbyname_ex",
"httpx.get",
"httpx.post",
"httpx.put",
@ -10440,6 +10490,90 @@ def _check_signal_escape_patterns(
# is extracted the same as a positional one.
_NET_URL_KWARGS = ("url",)
_NET_ADDR_KWARGS = ("address", "sock_addr")
# APIs whose FIRST positional (or host= keyword) argument is a bare HOST string rather than a
# URL: http.client.HTTP(S)Connection(host[, port]) and the socket name-resolution helpers. For
# these the literal arg is checked directly as a host (there is no scheme to parse out first).
_NET_HOST_APIS = frozenset(
{
"http.client.HTTPConnection",
"http.client.HTTPSConnection",
"socket.getaddrinfo",
"socket.gethostbyname",
"socket.gethostbyname_ex",
}
)
_NET_HOST_KWARGS = ("host",)
# Network-client constructors whose INSTANCES expose request methods. A call chained directly
# off such a constructor -- requests.Session().get(url), httpx.Client().get(url),
# urllib.request.build_opener().open(url) -- has a short fq (just the method name), so it is
# matched by its receiver constructor instead of the module-rooted fq prefix.
_NET_CLIENT_CTORS = frozenset(
{
"requests.Session",
"requests.sessions.Session",
"httpx.Client",
"httpx.AsyncClient",
"aiohttp.ClientSession",
"urllib.request.build_opener",
"urllib3.PoolManager",
"urllib3.HTTPConnectionPool",
"urllib3.HTTPSConnectionPool",
"urllib3.connectionpool.HTTPConnectionPool",
"urllib3.connectionpool.HTTPSConnectionPool",
}
)
# Instance request methods. `.request(method, url)` carries the URL at arg1 (see below); the
# others take it at arg0. `.get`/`.open` etc. on a non-client receiver (dict.get, file.open)
# are excluded because the receiver must be a client-ctor Call or a tracked client alias.
_NET_CLIENT_METHODS = frozenset(
{
"get",
"post",
"put",
"delete",
"head",
"patch",
"options",
"request",
"open",
}
)
_NET_CLIENT_URL_AT_ARG1 = frozenset({"request"})
def _net_call_fq(_call):
# The alias-resolved fully-qualified name of a Call's callee (import requests as r ->
# r.Session() folds to requests.Session), or "" if it is not an attribute/name call.
if not isinstance(_call, ast.Call):
return ""
_parts: list[str] = []
_cur = _call.func
while isinstance(_cur, ast.Attribute):
_parts.insert(0, _cur.attr)
_cur = _cur.value
if isinstance(_cur, ast.Name):
_parts.insert(0, _cur.id)
if _parts and _parts[0] in _net_aliases:
_parts = _net_aliases[_parts[0]].split(".") + _parts[1:]
return ".".join(_parts) if _parts else ""
# Variables bound by a same-name single assignment to a network-client constructor, so a
# method call on the stored instance (s = requests.Session(); s.get(url)) is matched like the
# chained form. A name also assigned to any non-client value is excluded, so an unrelated
# .get/.open on a reused name is not mis-flagged.
_net_client_aliases: set[str] = set()
_net_client_disqualified: set[str] = set()
for _asn in ast.walk(tree):
if (
isinstance(_asn, ast.Assign)
and len(_asn.targets) == 1
and isinstance(_asn.targets[0], ast.Name)
):
_nm = _asn.targets[0].id
if _net_call_fq(_asn.value) in _NET_CLIENT_CTORS:
_net_client_aliases.add(_nm)
else:
_net_client_disqualified.add(_nm)
_net_client_aliases -= _net_client_disqualified
def _net_fold_str(_n):
# Fold a network target node to a concrete string: a module-level constant (via _const_env)
@ -10479,6 +10613,83 @@ def _check_signal_escape_patterns(
_m = re.match(r"^\w+://([^/?#]+)[/?#]", _pre)
return _m.group(1) if _m else None
def _net_check_target(
_node,
_a0,
is_host_api = False,
):
# Resolve a network call's target argument to a concrete host and record a block if it is
# a cloud-metadata host, an unresolved (opaque) target, or a host outside the allowlist.
# ``is_host_api`` marks callees whose literal arg is a bare host (HTTPConnection('h'),
# getaddrinfo('h', 80)) rather than a URL, so no scheme is parsed out.
_host = None
_url = None
_opaque = False
if _a0 is not None:
if isinstance(_a0, ast.Tuple) and _a0.elts:
_e0 = _a0.elts[0]
if isinstance(_e0, ast.Constant) and isinstance(_e0.value, str):
_host = _e0.value
else:
_folded = _net_fold_str(_e0)
if _folded is not None:
_host = _folded
else:
_opaque = True
elif isinstance(_a0, ast.Constant) and isinstance(_a0.value, str):
if is_host_api:
_host = _a0.value
else:
_url = _a0.value
else:
_folded = _net_fold_str(_a0)
if _folded is not None:
if is_host_api:
_host = _folded
else:
_url = _folded
else:
_pref = _net_literal_host_prefix(_a0)
if _pref is not None:
_host = _pref
else:
_opaque = True
if _url and _host is None:
_m = re.match(r"^\w+://([^/?#]+)", _url)
if _m:
_host = _m.group(1)
if _opaque:
network_calls.append(
{
"type": "untrusted_host_blocked",
"line": getattr(_node, "lineno", -1),
"description": (
"Blocked: non-literal network target cannot be checked "
"against the sandbox allowlist"
),
}
)
elif _host:
if _is_metadata_host(_host):
network_calls.append(
{
"type": "metadata_host_blocked",
"line": getattr(_node, "lineno", -1),
"description": "Blocked: cloud-metadata host",
}
)
elif not _is_trusted_host(_host):
network_calls.append(
{
"type": "untrusted_host_blocked",
"line": getattr(_node, "lineno", -1),
"description": (
"Blocked: host not in sandbox allowlist; "
"use an allowed informational source"
),
}
)
class NetworkAndIoVisitor(ast.NodeVisitor):
def visit_Call(self, node):
parts: list[str] = []
@ -10579,86 +10790,41 @@ def _check_signal_escape_patterns(
}
)
# 2) Extract the host (URL string or (host, port) tuple). The host may be
# a positional first arg OR a keyword (requests.get(url=...),
# urlopen(url=...), create_connection(address=(host, port))). A non-literal
# arg is first folded to a concrete string (u = 'http://x'; get(u)), then
# reduced to its leading literal host prefix (f'https://hf.co/{path}', a
# 'https://hf.co/' + p concat) when a / ? # terminates the host inside the
# literal so a dynamic tail cannot extend it. A target that stays fully
# opaque fails closed: there is no runtime network filter, so an unresolved
# host (urlopen(user_input)) cannot be proven to be on the allowlist.
host_arg = None
url_arg = None
host_opaque = False
# 2) Extract the host (URL string, bare host, or (host, port) tuple) and check
# it. The target may be a positional first arg OR a keyword (requests.get(url=...),
# urlopen(url=...), create_connection(address=(host, port)), HTTPConnection(
# host=...)). Bare-host callees (HTTPConnection, getaddrinfo) treat the literal
# arg as a host directly; everything else parses a scheme://host URL. A target
# that stays fully opaque fails closed. See _net_check_target.
a0 = node.args[0] if node.args else None
if a0 is None:
for _kw in node.keywords or []:
if _kw.arg in _NET_URL_KWARGS:
if _kw.arg in _NET_URL_KWARGS or _kw.arg in _NET_ADDR_KWARGS:
a0 = _kw.value
break
if _kw.arg in _NET_ADDR_KWARGS:
if fq in _NET_HOST_APIS and _kw.arg in _NET_HOST_KWARGS:
a0 = _kw.value
break
if a0 is not None:
if isinstance(a0, ast.Tuple) and a0.elts:
e0 = a0.elts[0]
if isinstance(e0, ast.Constant) and isinstance(e0.value, str):
host_arg = e0.value
else:
_folded = _net_fold_str(e0)
if _folded is not None:
host_arg = _folded
else:
host_opaque = True
elif isinstance(a0, ast.Constant) and isinstance(a0.value, str):
url_arg = a0.value
else:
_folded = _net_fold_str(a0)
if _folded is not None:
url_arg = _folded
else:
_pref = _net_literal_host_prefix(a0)
if _pref is not None:
host_arg = _pref
else:
host_opaque = True
if url_arg and host_arg is None:
m = re.match(r"^\w+://([^/?#]+)", url_arg)
if m:
host_arg = m.group(1)
_net_check_target(node, a0, is_host_api = (fq in _NET_HOST_APIS))
if host_opaque:
network_calls.append(
{
"type": "untrusted_host_blocked",
"line": getattr(node, "lineno", -1),
"description": (
"Blocked: non-literal network target cannot be checked "
"against the sandbox allowlist"
),
}
)
elif host_arg:
if _is_metadata_host(host_arg):
network_calls.append(
{
"type": "metadata_host_blocked",
"line": getattr(node, "lineno", -1),
"description": "Blocked: cloud-metadata host",
}
)
elif not _is_trusted_host(host_arg):
network_calls.append(
{
"type": "untrusted_host_blocked",
"line": getattr(node, "lineno", -1),
"description": (
"Blocked: host not in sandbox allowlist; "
"use an allowed informational source"
),
}
)
# Client-instance request call: requests.Session().get(url), httpx.Client().get(url),
# build_opener().open(url), or s.get(url) where s was bound to a client constructor.
# The chained fq is just the method name, so match by the receiver being a client-ctor
# Call or a tracked client alias. .get/.open on a plain dict/file receiver is excluded.
if isinstance(node.func, ast.Attribute) and node.func.attr in _NET_CLIENT_METHODS:
_recv = node.func.value
_is_client = (
isinstance(_recv, ast.Call) and _net_call_fq(_recv) in _NET_CLIENT_CTORS
) or (isinstance(_recv, ast.Name) and _recv.id in _net_client_aliases)
if _is_client:
_idx = 1 if node.func.attr in _NET_CLIENT_URL_AT_ARG1 else 0
_ca0 = node.args[_idx] if len(node.args) > _idx else None
if _ca0 is None:
for _kw in node.keywords or []:
if _kw.arg in _NET_URL_KWARGS:
_ca0 = _kw.value
break
_net_check_target(node, _ca0, is_host_api = False)
is_open_call = (
(isinstance(node.func, ast.Name) and node.func.id == "open")
@ -12811,7 +12977,9 @@ def _inject_sandbox_guard(code: str, prelude: str) -> str:
``from __future__`` imports must be the first statement of a module (only a
docstring and comments may precede them), so blindly prepending the guard line
turns any user program that opens with a future import into a SyntaxError. Parse
turns any user program that opens with a future import into a SyntaxError. A
leading string literal is likewise the module docstring only while it is the FIRST
statement, so prepending the guard ahead of it would make ``__doc__`` None. Parse
the code, keep a leading module docstring and any ``from __future__`` imports on
top, and insert the (inert compile-time) guard immediately after them -- it still
runs before the first real user statement, so the sandbox is established before
@ -12833,16 +13001,16 @@ def _inject_sandbox_guard(code: str, prelude: str) -> str:
):
idx = 1
split = body[0].end_lineno or 0
has_future = False
while (
idx < len(body)
and isinstance(body[idx], ast.ImportFrom)
and body[idx].module == "__future__"
):
has_future = True
split = body[idx].end_lineno or split
idx += 1
if not has_future or split <= 0:
# Splice after the head only when there is something that MUST stay first (a leading
# docstring and/or future imports); otherwise a plain prepend is correct and cheaper.
if idx == 0 or split <= 0:
return prelude + code
# Split at the last head statement's exact END COLUMN, not the whole physical line: a
# `from __future__ import annotations; open('/tmp/x','w')` puts a real statement on the SAME

View file

@ -2430,3 +2430,34 @@ def test_sandboxed_future_import_own_line_benign_allowed():
)
assert "WROTE_OK" in out
assert "sandbox:" not in out
@_POSIX_ONLY
def test_sandboxed_module_docstring_preserved():
# A leading string literal is the module docstring only while it is the FIRST statement, so the
# guard prelude must be spliced AFTER it (not prepended) -- otherwise __doc__ becomes None.
out = _python_exec(
'"""studio doc marker"""\nprint(__doc__)',
None,
30,
"backstop-docstring",
disable_sandbox = False,
)
assert "studio doc marker" in out
assert "sandbox:" not in out
@_POSIX_ONLY
def test_sandboxed_docstring_same_line_write_denied(tmp_path):
# A `"""doc"""; open(<outside>, 'w')` puts a real write on the SAME line as the docstring; the
# guard prelude must still be installed BEFORE that write while keeping the docstring first.
target = tmp_path / "docstring_sameline_escape.txt"
out = _python_exec(
f'"""doc"""; open({str(target)!r}, "w").write("x"); print("DONE")',
None,
30,
"backstop-docstring-sameline",
disable_sandbox = False,
)
assert "sandbox:" in out or "PermissionError" in out
assert not target.exists()

View file

@ -5753,3 +5753,100 @@ class TestRound58Bypasses:
)
def test_round58_benign_allowed(self, code):
_ok(code)
class TestRound59Bypasses:
# A constant-key namespace-dict lookup (globals()['f'] / locals()['f'] / vars()['f']) reads a
# name from the caller namespace without a Name node, so the exec/eval outward-reference model
# must treat that key as a free reference -- exec("globals()['f']('touch /tmp/p')") reaches the
# caller's f = os.system.
@pytest.mark.parametrize(
"ns",
["globals", "locals", "vars"],
)
def test_exec_namespace_dict_alias(self, ns):
_blocked(
"import os\nf = os.system\nexec(\"%s()['f']('touch /tmp/p')\")" % ns,
expect_phrase = "caller alias 'f'",
)
def test_eval_namespace_dict_alias(self):
_blocked(
"import os\nf = os.system\neval(\"globals()['f']('touch /tmp/p')\")",
expect_phrase = "caller alias 'f'",
)
# Bare-host network APIs: http.client.HTTP(S)Connection(host) and socket name-resolution
# helpers take a HOST, not a URL, so the literal first arg (or host= keyword) is checked
# directly against the metadata denylist / allowlist instead of being parsed as a scheme URL.
@pytest.mark.parametrize(
"code",
[
'import http.client\nhttp.client.HTTPConnection("169.254.169.254")',
'import http.client\nhttp.client.HTTPSConnection("169.254.169.254", 443)',
'import http.client\nhttp.client.HTTPConnection(host="169.254.169.254")',
],
)
def test_bare_host_metadata_blocked(self, code):
_blocked(code, expect_phrase = "cloud-metadata host")
@pytest.mark.parametrize(
"code",
[
'import socket\nsocket.getaddrinfo("untrusted.example", 80)',
'import socket\nsocket.gethostbyname("untrusted.example")',
'import http.client\nhttp.client.HTTPConnection("untrusted.example")',
],
)
def test_bare_host_untrusted_blocked(self, code):
_blocked(code, expect_phrase = "not in sandbox allowlist")
# Client-instance request calls: the chained fq is only the method name, so match by the
# receiver being a client-ctor Call (requests.Session().get) or a same-name single-assignment
# alias (s = requests.Session(); s.get). .request(method, url) carries the URL at arg1.
@pytest.mark.parametrize(
"code",
[
'import requests\nrequests.Session().get("http://169.254.169.254/latest")',
'import httpx\nhttpx.Client().get("http://169.254.169.254/latest")',
'import httpx\nhttpx.AsyncClient().get("http://169.254.169.254/latest")',
'import urllib.request\nurllib.request.build_opener().open("http://169.254.169.254/")',
'import requests\ns = requests.Session()\ns.get("http://169.254.169.254/x")',
'import httpx\nhttpx.Client().request("GET", "http://169.254.169.254/x")',
],
)
def test_client_instance_network_blocked(self, code):
_blocked(code, expect_phrase = "cloud-metadata host")
# shuf -o / uniq output-operand writers escape the workdir in an unguarded child, so they are
# blocked like sort -o (full-block, since the realpath backstop cannot see the child).
@pytest.mark.parametrize(
"cmd",
[
"shuf -e a b -o /tmp/p", # shuf --output
"shuf --output=/tmp/p f",
"uniq /dev/null /tmp/p", # second (output) operand
"uniq data.txt /tmp/out",
],
)
def test_shuf_uniq_output_writers(self, cmd):
_blocked(_sh(cmd), expect_phrase = "blocked command")
@pytest.mark.parametrize(
"code",
[
# Benign round-59 forms stay allowed.
'import requests\nrequests.get("https://huggingface.co/x")',
'import requests\nrequests.Session().get("https://huggingface.co/x")',
'import http.client\nhttp.client.HTTPConnection("huggingface.co")',
'import socket\nsocket.getaddrinfo("huggingface.co", 443)',
'd = {}\nd.get("http://169.254.169.254")', # dict.get is not a network call
'f = open("local.txt")\nf.read()', # file .open/.read, not a client
"exec('a = 1 + 2')", # benign exec payload, no caller alias
_sh("shuf -e a b c"), # shuf with no output file
_sh("uniq data.txt"), # uniq with a single (input) operand
_sh("uniq -f 3 data.txt"), # uniq skip-fields count is not an output operand
],
)
def test_round59_benign_allowed(self, code):
_ok(code)