Commit ebc951d
committed
Close a real sandbox escape: dir_fd= bypasses the workspace write grant
check_path() resolves a call's path argument against the process's cwd,
pinned to the workspace by os.chdir(). Every mutating os function that
accepts dir_fd=/src_dir_fd=/dst_dir_fd= resolves the same string against an
open directory descriptor instead, and cwd never enters into it — so a tool
that legitimately opens a runtime path for reading (site-packages, which has
to stay readable so imports work) can get a descriptor for it and then write
there via that descriptor while check_path validates a path that has nothing
to do with where the write actually lands.
Verified end to end: a tool opens site-packages (a legitimate read), gets a
dir_fd from it, and calls os.open("evil.pth", O_CREAT|O_WRONLY,
dir_fd=that_fd). No SandboxViolation was raised, the file landed in
site-packages, and it executed automatically on the next fresh interpreter
start in that environment — the exact .pth-drop escape the read/write grant
split (and the existing os.readlink guard) exists to close, reopened through
a syscall shape the audit-event path check never considered a path argument
for at all. os.mkdir, os.remove, and os.rename with dir_fd= reproduce the
same hole.
Fix: _install_dir_fd_guard() wraps every stdlib function that accepts one of
the three dir_fd keyword spellings (chmod, chown, link, mkdir, mkfifo,
mknod, open, remove, rename, replace, rmdir, symlink, unlink, utime) and
refuses the keyword outright, the same way the existing os.readlink guard
already refuses dir_fd for the one function it covers — there is no reliable
way to turn a directory descriptor back into the path it names, so there is
nothing to check against the grant. Derived from the stdlib's own three
keyword spellings rather than a hand-maintained per-function table, so it
does not go stale the way the fork_exec arity table already did once.
Added test_gate_dot_pth_cannot_be_planted_via_dir_fd (4 parametrized cases:
os.open, os.mkdir, os.remove, os.rename), sitting next to the existing
plain-path .pth-planting gate test it mirrors.
Verified: full suite green on Python 3.12 and 3.13; ruff clean; confirmed
normal (non-dir_fd) file operations inside the workspace are unaffected.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>1 parent c3d8001 commit ebc951d
2 files changed
Lines changed: 142 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
383 | 383 | | |
384 | 384 | | |
385 | 385 | | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
386 | 464 | | |
387 | 465 | | |
388 | 466 | | |
| |||
531 | 609 | | |
532 | 610 | | |
533 | 611 | | |
| 612 | + | |
534 | 613 | | |
535 | 614 | | |
536 | 615 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
737 | 737 | | |
738 | 738 | | |
739 | 739 | | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
740 | 803 | | |
741 | 804 | | |
742 | 805 | | |
| |||
0 commit comments