从恶意 Dataset 到横向移动:一套可落地的 Dataset Processing Threat Model(资产边界 + 威胁枚举 + 5 层控制)
从恶意 Dataset 到横向移动:一套可落地的 Dataset Processing Threat ModelTL;DR场景:2026-07-13 当周 Hugging Face 平台披露,攻击者通过上传恶意 Dataset 触发 Remote-code dataset loader Template injection 两条代码执行路径,在数据处理 Worker 上取得执行权限,然后提权到节点并横向移动到多个内部集群,收割云与集群凭据。结论:Dataset 处理的真正风险不是文件本身,而是读取动作被升级为任意代码执行——Loader、模板、依赖、网络与身份任一环节失控,都可能把普通数据处理变成横向移动的起点。控制目标不是堵住所有漏洞,而是让任意代码执行无法升级为节点、凭据和集群入侵。产出:覆盖资产/信任边界、8 大威胁枚举、Canonical Manifest、Admission Control 七条规则、一次性 Worker 基线、默认拒绝网络、短期身份、运行时证据、6 次攻击验证和典型失败模式,作为可落地的 Dataset Processing Threat Model 蓝本。版本矩阵功能状态说明Hugging Face 2026-07-13 当周遭遇 AI Agent 自主攻击✅ 已验证Hugging Face 7-16 官方公告 腾讯/IT之家 7-20 多源报道攻击路径:恶意 Dataset → Remote-code dataset loader Template injection → Worker 执行✅ 已验证Hugging Face 7-16 公告原文 7-20 腾讯新闻详细复盘提权到节点级、收割云与集群凭据、周末横向移动到多个内部集群✅ 已验证HF 7-16 公告原文,7-20 IT之家 报道攻击使用大量短生命周期沙箱、C2 自迁移到公共服务✅ 已验证HF 7-16 公告,7-20 深度复盘留下超过 1.7 万条操作日志,后续用 GLM 5.2 国产开源模型取证✅ 已验证7-21 港股 AI 报道 7-20 腾讯新闻影响少量内部数据集和服务凭证,公共模型/数据集/Spaces/容器镜像/已发布包未受影响✅ 已验证HF 7-16 公告原文HF 已移除所有立足点、重建受损节点、撤销并轮换所有受影响凭据与令牌✅ 已验证7-20 腾讯新闻详细复盘Kubernetes Pod Security Standards / Network Policies / Service Accounts 官方文档✅ 已验证文章参考链接 1-3,6 均为 K8s 官方gVisor Kubernetes Quick Start 文档✅ 已验证文章参考链接 4Kubernetes Linux Kernel Security Constraints(Seccomp/AppArmor/SELinux)✅ 已验证文章参考链接 5ttlSecondsAfterFinished: 300runtimeClassName: gvisorreadOnlyRootFilesystem: true是一次性 Worker 常见组合✅ 已验证K8s Job/gVisor 官方推荐用法automountServiceAccountToken: false阻断默认 Token 挂载✅ 已验证K8s ServiceAccount 官方建议NetworkPolicy podSelector: {} policyTypes: [Ingress, Egress]默认拒绝命名空间✅ 已验证K8s NetworkPolicy 官方默认拒绝模式域名级 Egress 控制通常需要 Egress Proxy / Service Mesh / 云防火墙补充✅ 已验证K8s NetworkPolicy 仅基于 IP/Port,K8s 官方文档明确hf://org/namerevision是 Hugging Face Hub 数据集标准引用格式✅ 已验证HF Datasets 官方文档发布边界本文给出的是供应链威胁模型与示意配置不是适用于所有集群的可直接部署清单gVisor、Kata、NetworkPolicy 与工作负载身份必须按实际平台兼容性验证。发布边界本文给出的是供应链威胁模型与示意配置不是适用于所有集群的可直接部署清单gVisor、Kata、NetworkPolicy 与工作负载身份必须按实际平台兼容性验证。核心结论安全设计必须假设 Dataset、Loader、模板和依赖中至少有一项会执行任意代码。控制目标不是阻止所有漏洞而是让任意代码执行无法升级为节点、凭据和集群入侵。资产与信任边界需要保护的资产包括租户数据、内部 Dataset、云与集群身份、对象存储、模型与镜像 Registry、处理结果完整性、审计日志和平台可用性。信任边界至少有五层上传入口Manifest 与策略层执行 WorkerNode/Runtime内部服务与云控制面。只在上传入口做扫描会漏掉运行时产生的下载、动态依赖、模板展开和第二阶段 Payload。威胁枚举威胁典型路径核心控制Loader 任意代码执行remote code、dynamic import、setup hook禁用默认执行、Allowlist、静态与动态分析模板注入配置值进入解释器/模板引擎无逻辑模板、严格 Schema、输出编码依赖投毒动态安装 PyPI/Git 依赖锁文件、私有镜像、Digest、离线依赖宿主逃逸或过度权限privileged、hostPath、runtime socketRestricted Policy、无特权、沙箱运行时凭据窃取env、Secret mount、metadata endpoint短期工作负载身份、无默认 Token横向移动内部 DNS/API/Registry 可达默认拒绝 Egress、目的地 Allowlist结果投毒修改处理结果、缓存或索引内容寻址、签名、双通道验证日志规避删除容器或短命进程Node/控制面外部不可变采集Canonical Manifest所有待处理资产先归一化为可签名 Manifest。名称不是信任依据Digest 和解析后的实际执行计划才是。apiVersion:processing.ascendlab.dev/v1kind:DatasetJobManifestmetadata:tenant:tenant_123job_id:job_20260718_001spec:dataset:source:hf://org/namerevisioncontent_digest:sha256:...loader:mode:declarative-onlyartifact_digest:sha256:...remote_code:falsedependencies:lock_digest:sha256:...network_install:falseexecution:image_digest:registry/appsha256:...timeout_seconds:300cpu:2memory:4Ginetwork:policy:deny-by-defaultallow:-host:object-store.internalport:443identity:audience:dataset-processorttl_seconds:600Fingerprint 应覆盖规范化后的 Dataset Revision、Loader、模板、依赖锁文件、容器镜像、命令、参数、网络策略和身份策略。任何关键项变化都应重新进入审批或隔离队列。Admission ControlAdmission 不只检查 Kubernetes 字段还要检查业务级 Manifest禁止remote_codetrue进入普通 Worker Pool。镜像必须使用 Digest不允许可变 Tag。禁止privileged、hostNetwork、hostPID、hostIPC、hostPath和容器运行时 Socket。禁止自动挂载 ServiceAccount Token。只允许经过签名的 Loader、镜像和依赖清单。网络 Allowlist 必须非空且与任务类型匹配。高风险任务进入 gVisor/Kata/VM 级隔离池而不是普通容器池。一次性 Worker 基线下面是示意配置不是可直接复制到所有集群的完整生产清单apiVersion:batch/v1kind:Jobmetadata:name:dataset-job-20260718-001namespace:untrusted-processingspec:ttlSecondsAfterFinished:300template:spec:automountServiceAccountToken:falserestartPolicy:NeverruntimeClassName:gvisorsecurityContext:runAsNonRoot:trueseccompProfile:type:RuntimeDefaultcontainers:-name:workerimage:registry/processorsha256:...securityContext:allowPrivilegeEscalation:falsereadOnlyRootFilesystem:truecapabilities:drop:[ALL]resources:limits:cpu:2memory:4Giephemeral-storage:8GivolumeMounts:-name:scratchmountPath:/workvolumes:-name:scratchemptyDir:sizeLimit:8GiRestricted Pod Security、Seccomp/AppArmor/SELinux 和专用沙箱运行时解决不同层次的问题不能互相替代。[1][4][5]默认拒绝网络apiVersion:networking.k8s.io/v1kind:NetworkPolicymetadata:name:deny-allnamespace:untrusted-processingspec:podSelector:{}policyTypes:[Ingress,Egress]随后按 FQDN Gateway、固定代理或受控对象存储端点放行。原生 NetworkPolicy 主要基于 IP/Port域名级控制通常需要 Egress Proxy、Service Mesh 或云防火墙补充。[2]必须显式阻断云 Metadata Endpoint、Kubernetes API Server除非有严格代理、容器 Registry 管理接口、CI/CD、Secret Manager 管理面和非任务相关内部网段。短期身份身份应满足任务绑定、受众限制、十分钟级 TTL、最小 Scope、不可横向复用、任务结束自动撤销。Worker 不应持有可创建新身份、读取其他租户对象或修改控制面的权限。Kubernetes Secret 需要加密、最小 RBAC 和审计但更优方案是按任务签发短期身份而不是挂载长期 Secret。[3]运行时证据每个任务至少保留Manifest Digest、镜像 Digest、Node、Runtime Class、进程树、网络连接、文件写入摘要、身份签发与使用、策略判定、输出 Digest 和销毁时间。日志需要在 Worker 与 Node 之外写入不可变存储防止攻击者清理现场。验证方法在无真实凭据的测试集群执行恶意 Loader确认无法访问 Metadata、API Server、邻接 Pod 和宿主路径。注入 DNS 隧道、反向连接和大流量下载验证 Egress 阻断与告警。尝试读取默认 ServiceAccount Token、环境变量和挂载 Secret。用可变 Tag 替换镜像确认 Admission 拒绝。修改 Loader 或配置模板确认 Fingerprint 变化触发重新审批。删除 Pod确认进程与网络证据仍在外部日志系统可检索。失败模式只做病毒扫描不做执行计划和依赖审计。允许 Worker 直接访问公网包仓库。所有任务共享同一个 Node Pool、缓存和 ServiceAccount。用 NetworkPolicy 替代沙箱运行时或用沙箱运行时替代身份最小化。签名通过后就假设内容安全。签名只证明来源和完整性不证明没有恶意逻辑。[6]参考资料Kubernetes Pod Security StandardsKubernetes Network PoliciesKubernetes Service Accounts 与短期 TokengVisor Kubernetes Quick StartKubernetes Linux Kernel Security ConstraintsKubernetes Secrets Good Practices错误速查卡症状根因定位修复Worker 执行后出现异常 Egress,触发告警Loader / 模板 / 依赖在运行时下载第二阶段 Payload,上传入口扫描未覆盖比对 Manifest 的网络 Allowlist 与实际 DNS/IP 流量;看是否动态下载二进制Manifest 加network_install: false 锁文件 默认拒绝 NetworkPolicy;Allowlist 必须非空HF 7-13 攻击:数据处理 Worker 被提权到节点remote_codetrue进入普通 Worker Pool,Admission 没拦截看 Admission 是否校验业务 Manifest,而非仅 K8s 字段Admission 加业务级规则:remote_codetrue必须进 gVisor/Kata 隔离池Dataset 处理后输出被篡改,索引或缓存命中错误结果缺少内容寻址与签名,Worker 可改写结果看输出是否带 Digest 校验、是否双通道验证输出带内容寻址 签名;接收端做双通道校验,不只信任一份路径攻击者 Pod 被删后无法追溯证据只写在 Pod 内,Pod 销毁随之消失看日志、进程、网络证据是否落到 Worker 之外的不可变存储用 DaemonSet / Node Agent 控制面外部对象存储采集,Pod 删后仍可检索Worker 能访问云 Metadata Endpoint 拿到长期凭据NetworkPolicy 未显式阻断 169.254.169.254,Pod 可达控制面在测试集群用恶意 Loader 探测 MetadataNetworkPolicy 显式路由表 Service Mesh 显式阻断 MetadataWorker 默认拿到 ServiceAccount Token,挂载到 /var/run/secrets没设置automountServiceAccountToken: false查 Job/Pod Spec 缺省值一次性 Worker 显式置 false;按任务签发短期 OIDC 身份镜像从v3浮动 Tag 拉取,版本漂移导致安全控制失效未使用 Digest,Admission 没校验尝试用可变 Tag 替换镜像,看是否被拒镜像必须固定sha256:...,Admission 拒绝可变 Tag短生命周期沙箱攻击者无法追踪攻击者用大量一次性容器自迁移 C2,日志只在本机看证据是否落 Node/控制面外部不可变存储,是否带时间戳强制 Node Agent 采集,所有连接/DNS/进程链入不可变日志用了沙箱运行时但没改网络/身份策略沙箱只解决进程边界,不解决凭据泄露看 Worker 是否仍可访问 Metadata、API Server、长期凭据沙箱 默认拒绝网络 短期身份必须同时启用,不能互相替代修改 Loader 或配置模板后未触发重新审批Fingerprint 只覆盖镜像,没覆盖 Loader 与模板修改 Loader 重新提交,看是否进入审批/隔离队列Fingerprint 覆盖 Dataset Revision、Loader、模板、依赖锁、镜像、命令、参数、网络、身份签名通过就当作内容安全签名只证明来源和完整性,不证明没有恶意逻辑比对签名验证流程与代码评审流程签名 静态分析 动态分析 人类审查四层叠加病毒扫描通过就允许任务上线扫描器识别不了 Loader RCE、模板注入、动态依赖注入恶意 Loader,看是否被病毒扫描检出病毒扫描只能作辅助;执行计划与依赖审计必须独立所有任务共享同一个 Node Pool、缓存、ServiceAccount没有按信任等级拆池看是否按namespace与runtimeClassName拆分高风险任务进隔离 Pool,缓存按信任域分离,ServiceAccount 按任务签发Worker 能下载公网 PyPI/Git 依赖允许pip install/npm install直连公网看 NetworkPolicy 与 Manifest 是否有network_install: falseManifest 强制锁文件 私有镜像 离线依赖攻击者访问到 CI/CD 与 Secret Manager 管理面Egress 放行过宽列出被允许的 Egress 目的地,看是否包含管理面显式阻断 CI/CD、Secret Manager、Registry 管理面、非任务相关内部网段