unsloth/studio
danielhanchen 17739721da studio/sandbox: close 7 bypass classes from cross-reviewer round-5 audit
Sonnet-panel review of round-4 surfaced seven concrete bypass classes
in the static gate. All seven are now closed (528 tests passing, 55
new R4 / R5 regression tests):

1. ``os.path.join`` alias bypasses. ``import os as o; o.path.join(...)``,
   ``from os.path import join`` (and ``as j``), ``from os import path``
   (and ``as op``), ``import posixpath as pp``, ``from posixpath import
   join`` -- previously the FQ match was literal-only (`os.path.join`,
   `posixpath.join`, `ntpath.join`). A pre-pass walk collects every
   alias of ``os`` / ``os.path`` / ``posixpath`` / ``ntpath`` and every
   from-import of ``join`` / ``expanduser``; the resolver checks
   ``<alias>.join`` and bare aliased names too.

2. ``shutil`` alias bypasses. ``import shutil as sh; sh.copy(...)``,
   ``from shutil import copyfile``, ``from shutil import move as mv``,
   etc. -- the file-copy gate matched only the literal ``shutil.X`` FQ.
   The pre-pass now tracks shutil module aliases and from-import
   aliases for ``copyfile`` / ``copy`` / ``copy2`` / ``copytree`` /
   ``move``; the gate canonicalises any matched alias to ``shutil.X``
   so the error message identifies the operation.

3. First-assignment-wins binding bypass. ``p = '/tmp/safe'; p =
   '/etc/shadow'; open(p)`` previously slipped because the pre-pass
   guard ``_target.id not in string_bindings`` ignored every
   reassignment, and the AST walk picked the safe value while Python
   uses last-wins at runtime. New ``string_bindings_all`` tracks every
   literal ever bound to a name; ``_record_string_binding`` biases the
   representative value toward sensitive-shaped paths via a substring
   hint set covering the credential / process-state root tokens. The
   reverse order (``shadow`` then ``safe``) is also caught.

4. Brace-expansion off-by-one. ``cat ~/.aws/{x0,...,x62,credentials}``
   exploited that ``_expand_brace_projections`` started with
   ``out = {original}`` (1 item) so a cap of 64 only left 63
   alternative slots. The inner loop also broke per-alternative on
   the cap, so the sensitive name at position 64+ was never reached.
   Raised the cap to 1024 and the inner loop now expands all
   alternatives of a brace in one pass before the outer cap can stop
   the queue.

5. ``thread-self`` in shell-expansion regex. ``cat /proc/thread-self/
   $(echo environ)`` was missed because ``_SENSITIVE_ROOT_WITH_EXPANSION_RE``
   only listed ``self|\d+`` in the ``/proc/...`` alternation, while
   ``_ABSOLUTE_SENSITIVE`` correctly included ``thread-self``. One
   alternation entry restores symmetry.

6. Eval / exec pre-pass not re-run. ``exec("p='/etc/shadow'\nopen(p)")``
   slipped because the inner AST visit ran without the string-binding
   pre-pass. Extracted the pre-pass into ``_run_string_binding_prepass``
   and call it on each inner literal payload before the visitor
   recurses, so payload-local variable assignments are visible.

7. Pathlib name binding pre-pass. ``p = Path('/etc/shadow');
   p.read_text()`` slipped because the pre-pass only resolved string
   literals -- pathlib constructor calls returned None and the bound
   name remained unresolved. Pre-pass now falls back to
   ``_extract_pathlib_target`` using per-tree alias sets so
   ``import pathlib as pl; p = pl.Path(...)`` and ``from pathlib import
   Path as P; p = P(...)`` both resolve. ``NamedExpr`` (walrus) is also
   surfaced by the pre-pass so walrus-inside-eval expressions are
   visible.

Pre-pass call order. The initial pre-pass invocation moves to AFTER
``_extract_pathlib_target`` is defined so the closure cell binds
correctly (Python looks up free variables in the enclosing scope at
CALL time, not at function-definition time).

Full sandbox suite: 528 passed (455 prior + 73 R4 / R5 regression tests).
2026-05-24 14:35:17 +00:00
..
backend studio/sandbox: close 7 bypass classes from cross-reviewer round-5 audit 2026-05-24 14:35:17 +00:00
frontend studio: fix toast close-button click and light-mode hover (#5597) 2026-05-19 00:55:55 -07:00
src-tauri studio: expose launcher capability bits on unauth /api/health (#5486) 2026-05-17 21:29:24 -07:00
__init__.py Final cleanup 2026-03-12 18:28:04 +00:00
install_llama_prebuilt.py tests/studio: lock in Windows GPU detection fix (#5106) with a synthetic CI test (#5376) 2026-05-18 00:06:01 -07:00
install_python_stack.py studio: skip flash-attn install on Blackwell GPUs (sm_100+) (#5420) 2026-05-14 18:13:50 +04:00
LICENSE.AGPL-3.0 Add AGPL-3.0 license to studio folder 2026-03-09 19:36:25 +00:00
setup.bat Final cleanup 2026-03-12 18:28:04 +00:00
setup.ps1 CI: scope GITHUB_TOKEN permissions, add MLX CI, unblock ~60 skipped tests (#5312) 2026-05-11 03:19:13 -07:00
setup.sh Route CPU-only Linux x86_64 to ggml-org/llama.cpp prebuilts (#5302) 2026-05-05 23:22:22 -07:00
Unsloth_Studio_Colab.ipynb studio: add --local to setup.sh + overlay unsloth-zoo from git main (#5252) 2026-05-02 08:51:56 +04:00