test(security): GHSA-f396-4rp4-7v2j Python regression + advisory note#540
Merged
Merged
Conversation
Add the reporter's exact PoC script (XlabAI Team / Tencent Xuanwu Lab) as a pytest integration test. The test builds a malicious OCI image with a symlink escape layer, loads it via boxlite.SimpleBox, and asserts the host path /tmp/boxlite_host_escape/pwned.txt is never written. Confirmed PASSED on macOS (Python 3.12, Hypervisor.framework) against the 0.9.4 SDK — SafeRoot lexical-walk containment holds. Linux (pathrs / openat2 RESOLVE_IN_ROOT) is covered by the existing extractor.rs regression tests (lines 1577–1650). Also records the advisory in the SECURITY.md Published Advisories table.
Comment on lines
+184
to
+186
| lyr_data = open( | ||
| os.path.join(OCI_LAYOUT_DIR, "blobs", "sha256", lyr_dgst), "rb" | ||
| ).read() |
| if os.path.exists(TARGET_FILE): | ||
| print("\n VULNERABLE — host file written successfully!") | ||
| print(f" Path: {TARGET_FILE}") | ||
| print(open(TARGET_FILE).read()) |
DorianZheng
added a commit
that referenced
this pull request
May 20, 2026
…#558) Brings SDK regression coverage in line with the existing Python tests (#539 / #540) and the Rust core test (src/boxlite/src/images/archive/extractor.rs::test_cve_symlink_escape_blocked). Node (vitest, *.integration.test.ts): - security-readonly-volume-remount: mounts a read-only host volume, runs `mount -o remount,rw` from inside the box, asserts the host file is unchanged. Counterpart of the Python remount test. - security-symlink-escape: builds a minimal malicious OCI layout inline (hand-rolled USTAR + sha256 + manifest/config/index, no new devDeps) and loads it via SimpleBox({ rootfsPath }), asserts no host file is written outside the extraction root. Go (//go:build boxlite_dev, *_integration_test.go): - security_readonly_volume_remount: same shape as the Node test, using WithVolumeReadOnly + box.Exec. - security_symlink_escape: uses stdlib archive/tar to build the malicious layer + json for the OCI layout, then rt.Create(..., WithRootfsPath(layoutDir)). C SDK regression coverage is intentionally skipped per sdks/c/tests/CMakeLists.txt: "lifecycle/execute/streaming/etc. tests were removed when the C SDK moved to the post-and-drain callback API; coverage of those code paths now lives in the Go SDK + runner integration suite." The new Go tests above cover the same C-FFI machinery from one layer up.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SYMLINK escape → /tmp, then writes through it), loads it viaboxlite.SimpleBox, and assertshost path /tmp/boxlite_host_escape/pwned.txtis never createdSECURITY.mdPublished Advisories table to record the advisory alongside GHSA-g6ww-w5j2-r7x3Test plan
pytest -m integration sdks/python/tests/test_symlink_escape.py -v -s— PASSED on macOS (Python 3.12, Hypervisor.framework, SDK 0.9.4)pathrs/openat2(RESOLVE_IN_ROOT)path covered by existingextractor.rsregression tests (lines 1577–1650)boxlite-prodrun pending (instance unreachable at time of commit; runpytestonce it's back up)