Audit remaining network tar extraction sites (vmm OCI layers, dstackup) after #881
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 48/100
Hướng nghiên cứu
Bắt đầu tại dstack/vmm/src/app/registry.rs ở extract_layer và hàm gọi nó là download_and_extract_layers, sau đó kiểm tra dstack/crates/dstackup/src/image.rs ở extract và so sánh với đường dẫn verifier đã được harden từ #881. Xác định policy về kiểu entry của OCI layer, cách xử lý các member bị bỏ qua, các member gzip, giới hạn kích thước và số lượng entry, cũng như việc dọn dẹp; hoàn thành khi cả hai vị trí extraction qua mạng đều tuân theo hành vi đã được ghi lại và kiểm thử.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Context
#881 hardened image archive extraction in dstack-verifier (download_image → extract_image_archive): entry paths are restricted to normal relative components, only regular files and directories are accepted, and tar::Entry::unpack_in confinement failures are treated as errors.
The same class of input — a tar archive fetched over the network and unpacked into a local directory — exists at two other call sites that #881 intentionally left out of scope. This issue tracks auditing them.
Call site 1: VMM OCI layer extraction (primary)
dstack/vmm/src/app/registry.rs:260 (extract_layer, reached from download_and_extract_layers at line 253):
let decoder = GzDecoder::new(data);
let mut archive = tar::Archive::new(decoder);
archive.unpack(dest).context("failed to extract gzipped tar layer")?;
This unpacks guest-image layers pulled from a container registry over the OCI Distribution API, before any measurement or signature check binds the content. Compared to the verifier path after #881:
- No entry-type allowlist. Symlinks, hardlinks, character/block devices and FIFOs in a layer are materialised on the host.
tar-rsonly special-cases dir/symlink/hardlink; other node types fall through to the generic unpack path. - Escaping entries are silently skipped, not rejected.
Archive::unpackcallsEntry::unpack_inper entry and discards thebool, so a member containing..is dropped without any error. The extraction reports success with a partial result. #881 explicitly turned this into a hard error for the verifier. - Single-member gzip only.
flate2::read::GzDecoderstops at the first gzip member and returns clean EOF;tar::Archivethen ends iteration with no error, so a multi-member layer extracts partially and silently. (Verified locally: a 2048-byte tar split across two concatenated gzip members yields 1024 bytes and 1 entry,err=None.) - Post-extraction cleanup is best-effort. The
for dir in &["dev", "etc", "proc", "sys"]loop usesfs_err::remove_dir(non-recursive) and ignores the result, so a non-emptyetc/from a layer survives.
Mitigations that are already present, for the record: tar-rs unpack_in drops .. members, canonicalises the parent directory via validate_inside_dst before writing (so symlink-through-parent traversal is blocked), and masks setuid/setgid off unless set_preserve_permissions(true) is called. So this is a hardening/robustness gap and an unhelpful-failure-mode problem, not a known traversal vulnerability.
Note that this call site cannot simply reuse #881's rule set: container rootfs layers legitimately contain symlinks and whiteout entries, so it needs its own policy (e.g. an explicit type allowlist, erroring on skipped members, MultiGzDecoder, and a decompressed-size / entry-count cap) rather than a copy of the verifier logic.
Call site 2: dstackup (secondary)
dstack/crates/dstackup/src/image.rs:752 (extract) shells out to tar -xzf ... --no-same-owner --no-same-permissions. Ownership and permission carry-over are already handled and the intent is documented in a comment. Remaining gaps are symlink/hardlink members and the absence of a size cap. Lower priority than call site 1.
Suggested scope
- Define and document the entry-type policy for OCI layer extraction in
vmm. - Turn silently-skipped (escaping) members into an error.
- Switch
GzDecoder→MultiGzDecoderinextract_layer. - Bound decompressed size and entry count for network-fetched archives (also missing in the verifier path after #881).
- Make the
dev/etc/proc/syscleanup explicit about what it does and does not remove, or drop it in favour of the type allowlist.
Refs: #881
- Ngôn ngữ chính
- Rust
- Star
- 551
- Fork
- 97
- Merge trung bình
- 1 ngày 8 giờ
- Pull request đã merge (30 ngày)
- 182
Chuẩn bị môi trường
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của Dstack-TEE/dstack
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
Dstack-TEE/dstack#1384 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 30/100
Dstack-TEE/dstack#1301 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 55/100
Dstack-TEE/dstack#1300 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
Dstack-TEE/dstack#1299 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
Dstack-TEE/dstack#1298 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của Dstack-TEE/dstack
Issue tương tự
-
`categorize_command` has no `uv` arm, so every `rtk uv …` row counts as `other` in the ecosystem mixĐang mởarea:api bug good first issue priority:low
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 92/100
rtk-ai/rtk#4316 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 92/100
Maintainer thường phản hồi trong vòng 1 ngày
-
area/cli kind/bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 90/100
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
-
good first issue open-endedness: low type: new feature
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100