Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Audit remaining network tar extraction sites (vmm OCI layers, dstackup) after #881

未关闭
#991 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
48/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
冷清
技术栈
rust
领域
security

调研方向

从 dstack/vmm/src/app/registry.rs 中的 extract_layer 及其调用者 download_and_extract_layers 开始,然后检查 dstack/crates/dstackup/src/image.rs 中的 extract,并与 #881 中强化后的 verifier 路径进行比较。定义 OCI layer 条目类型策略、跳过成员的处理方式、gzip 成员、大小和条目数量限制,以及清理;完成的标准是两个网络提取位置都遵循有文档记录且经过测试的行为。

由索引模型根据 Issue 内容生成。

描述

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-rs only special-cases dir/symlink/hardlink; other node types fall through to the generic unpack path.
  • Escaping entries are silently skipped, not rejected. Archive::unpack calls Entry::unpack_in per entry and discards the bool, 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::GzDecoder stops at the first gzip member and returns clean EOF; tar::Archive then 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 uses fs_err::remove_dir (non-recursive) and ignores the result, so a non-empty etc/ 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 → MultiGzDecoder in extract_layer.
  • Bound decompressed size and entry count for network-fetched archives (also missing in the verifier path after #881).
  • Make the dev/etc/proc/sys cleanup explicit about what it does and does not remove, or drop it in favour of the type allowlist.

Refs: #881

主要语言
Rust
星标
555
派生
97
平均合并
1 天 3 小时
30 天内合并 PR
195

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

Dstack-TEE/dstack 的其他 Issue

查看 Dstack-TEE/dstack 的全部 Issue

相似的 Issue

更多 Rust Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。