展示 HN:在 gVisor 沙箱中运行 GitHub Actions 步骤
Show HN: Run a GitHub Actions step in a gVisor sandbox

原始链接: https://github.com/geomys/sandboxed-step

## 使用 gVisor 的沙盒化 GitHub Actions 这个 GitHub Action `geomys/sandboxed-step` 通过在 gVisor 沙盒中运行命令来增强工作流的安全性。即使具有只读权限的标准 GitHub Actions,也容易受到缓存中毒的影响,并且缺乏步骤之间的真正隔离——所有步骤都在同一虚拟机上以 root 权限运行。此 action 解决了这些问题,为执行潜在的不受信任的代码(例如获取最新的依赖项)提供了一个更安全的环境。 该沙盒利用 Ubuntu-24.04 根文件系统,并提供对 `GITHUB_WORKSPACE`(默认情况下非持久化)、主机网络和环境变量的访问。它以与 runner 相同的用户身份运行,具有 sudo 访问权限,并且可以只读访问通过 `setup-*` actions 安装的工具。 **主要特性与安全注意事项:** * **凭证保护:** 该 action *要求* 在 `actions/checkout` 中禁用凭证持久化 (`persist-credentials: false`),以防止 token 泄露。 * **持久化:** 可以使用 `persist-workspace-changes: true` 持久化工作区更改,但由于安全风险,不建议这样做。 * **不可变发布:** 使用 GitHub 的不可变发布来确保标签安全。 此 action 提供了一个重要的安全层,对于处理外部依赖项和潜在供应链攻击的 CI/CD 管道尤其有价值。

一种新工具允许开发者在 gVisor 沙箱中运行 GitHub Actions 步骤,通过隔离代码执行来增强安全性。FiloSottile 在 Hacker News 上分享了这个项目 ([github.com/geomys](https://github.com/geomys)),该项目因其简单易用而受到赞扬,为常见的开发任务带来了一定程度的隔离。 用户强调了创建者持续交付有价值的安全技术的贡献。然而,有评论指出一个潜在的漏洞:即使是只读的 GitHub Actions 也可以接收到缓存写入令牌,从而可能导致缓存中毒。建议的解决方案包括限制只读操作的写入权限,或分层缓存以防止污染。 讨论强调了安全编码实践的重要性,以及像 gVisor 这样的工具在降低 CI/CD 管道中的风险方面的益处。
相关文章

原文

A GitHub Action that runs commands in a gVisor sandbox.

Surprisingly enough, GitHub Actions with read-only permissions still receive a cache write token, allowing cache poisoning, so they are not safe to run untrusted code.

Moreover, there is no isolation between steps in a workflow, since they all run on the same VM with root access. The only alternative is separating workflows with workflow_run, but that has its own limitations and overhead.

This can lead to a false sense of security when running untrusted code in a workflow or step with read-only permissions, despite defaulting workflows to read-only permissions being a top-level feature.

This Action runs commands in an isolated gVisor sandbox, allowing e.g. running CI against the latest versions of dependencies without risking being affected by supply chain attacks.

- uses: geomys/[email protected]
  with:
    run: |
      go get -u && go mod tidy
      go test ./...

The commands run in a gVisor sandbox with

  • a root filesystem similar to ubuntu-24.04 (ghcr.io/catthehacker/ubuntu:runner-24.04)
  • overlayed access to GITHUB_WORKSPACE (changes do not persist by default)
  • GITHUB_WORKSPACE working directory
  • host network access
  • allow-listed environment variables
  • same user as the GitHub Actions runner, with sudo access
  • read-only access to tools installed by setup-* actions (via RUNNER_TOOL_CACHE)

Changes to the workspace inside the sandbox can be made to persist on the host by setting persist-workspace-changes: 'true'. This is unlikely to be safe, as following steps will need to treat the workspace as untrusted.

Note

This action will detect and fail if the actions/checkout Action has persisted authentication tokens in GITHUB_WORKSPACE (the default behavior).

To use this action, you must disable credential persistence in your checkout step:

- uses: actions/checkout@v4
  with:
    persist-credentials: false

Alternatively, you can set allow-checkout-credentials: true to bypass this check, but this is NOT RECOMMENDED as it will expose the GitHub token to the sandbox.

All tags use GitHub's Immutable Releases, so they can't be changed even if this repository is compromised.

  • run (required): Commands to run in the sandbox
  • env (optional): Additional environment variables to set in the sandbox (one per line, KEY=VALUE format)
  • persist-workspace-changes (optional, default: false): Allow changes to persist on the host
  • disable-network (optional, default: false): Disable network access in the sandbox
  • allow-checkout-credentials (optional, default: false): Allow persisted checkout credentials
  • rootfs-image (optional): Docker image to use as the root filesystem

Example for sandboxed Go tests with latest dependencies

name: Go tests
on:
  push:
  pull_request:
  schedule: # daily at 09:42 UTC
    - cron: '42 9 * * *'
  workflow_dispatch:
permissions:
  contents: read
jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        go:
          - { go-version: stable }
          - { go-version: oldstable }
          - { go-version-file: go.mod }
        deps:
          - locked
          - latest
    steps:
      - uses: actions/checkout@v5
        with:
          persist-credentials: false
      - uses: actions/setup-go@v6
        with:
          go-version: ${{ matrix.go.go-version }}
          go-version-file: ${{ matrix.go.go-version-file }}
      - uses: geomys/[email protected]
        with:
          run: |
            if [ "${{ matrix.deps }}" = "latest" ]; then
              go get -u && go mod tidy
            fi
            go test ./...
  staticcheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
        with:
          persist-credentials: false
      - uses: actions/setup-go@v6
        with:
          go-version: stable
      - uses: geomys/[email protected]
        with:
          run: go run honnef.co/go/tools/cmd/staticcheck@latest ./...
  govulncheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
        with:
          persist-credentials: false
      - uses: actions/setup-go@v6
        with:
          go-version: stable
      - uses: geomys/[email protected]
        with:
          run: go run golang.org/x/vuln/cmd/govulncheck@latest ./...
联系我们 contact @ memedata.com