> For the complete documentation index, see [llms.txt](https://gitbook.cdxiaodong.life/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gitbook.cdxiaodong.life/cicd-an-quan/github-an-quan/actions.md).

# GitHub Actions

## 允许的不安全命令

有一些已弃用的 `set-env` 和 `add-path` 工作流命令，可以通过将 `ACTIONS_ALLOW_UNSECURE_COMMANDS` 环境变量设置为 `true` 来显式启用。

* `set-env` 通过以下工作流命令设置环境变量 `::set-env name=<NAME>::<VALUE>`
* `add-path` 通过以下工作流命令更新 `PATH` 环境变量 `::add-path::<VALUE>`

根据环境变量的使用情况，在最坏的情况下，这可能允许攻击者更改路径并运行非预期的命令，导致任意命令执行。例如，考虑以下工作流：

```yaml
name: 易受攻击的工作流

on:
  pull_request_target

env:
  # 1. 启用不安全命令
  ACTIONS_ALLOW_UNSECURE_COMMANDS: true
  ENVIRONMENT_NAME: prod

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      # 2. 打印 github 上下文
      - run: |
          print("""${{ toJSON(github) }}""")
        shell: python
      - name: 创建新的 PR 部署
        uses: actions/github-script@v5
        with:
          # 3. 创建部署
          script: |
            return await github.rest.repos.createDeployment({
                ...context.repo,
                ref: context.payload.pull_request.head.sha,
                auto_merge: false,
                required_contexts: [],
                environment: "${{ env.ENVIRONMENT_NAME }}",
                transient_environment: false,
                production_environment: false,
            });
          github-token: ${{ secrets.GITHUB_TOKEN }}
```

上述工作流通过在 `env` 部分将 `ACTIONS_ALLOW_UNSECURE_COMMANDS` 设置为 `true` 来启用不安全命令。可以看到，`deploy` 作业的第一步将 `github` 上下文打印到工作流日志中。由于 `github` 上下文中的部分变量是用户控制的，可能滥用不安全命令来设置任意环境变量。例如，攻击者可以使用拉取请求描述来传递以下payload，当打印 `github` 上下文时，这将重置 `ENVIRONMENT_NAME`：

```
\n::set-env name=ENVIRONMENT_NAME::", <YOUR_JS_CODE>//\n
```

{% hint style="info" %}
请注意，在2020年5月，GitHub 弃用了这些不安全的工作流命令。从那时起，GitHub 推荐使用环境文件：

* [GITHUB\_ENV](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-environment-variable) 设置环境变量
* [GITHUB\_PATH](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path) 添加系统路径

然而，GitHub 仍然提供 `ACTIONS_ALLOW_UNSECURE_COMMANDS` 环境变量来启用已弃用的命令，以保持向后兼容性。
{% endhint %}

现在让我们看看上述payload的工作原理：

![](https://github.com/cdxiaodong/cheat-sheets-cn/blob/master/CI%20CD/Github/img/set-env-payload.png)

由于 payload 使用了 `::set-env name=ENVIRONMENT_NAME::` 命令，它将把环境变量 `ENVIRONMENT_NAME` 重置为 `", <YOUR_JS_CODE>//`。因此，在 `github-script` 中，`environment` 将被设置为 `", <YOUR_JS_CODE>//` 而不是 `prod`。然后，攻击者可以通过精心设计的 `YOUR_JS_CODE` 注入任意 JavaScript 代码。

{% hint style="info" %}
实际上，`github-script` 的实现使用 `new Function(...)` 来评估 JavaScript 代码，这可能导致远程代码执行。
{% endhint %}

## 参考资料

* [GitHub Actions：在 GitHub Actions 工作流中执行远程代码](https://blog.christophetd.fr/remote-code-execution-in-github-actions-workflows/)
* [GitHub Actions：利用 GitHub Actions 中的注入漏洞](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/)
* [GitHub Actions：如何使用 GitHub Actions 的工作流命令](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions)

### 脚本注入

GitHub Actions 允许您使用各种shell在运行器上执行命令。这些shell包括 `bash`、`pwsh`、`powershell` 和 `python`。然而，在某些情况下，GitHub Actions 会将用户控制的输入直接传递给shell命令，这可能导致命令注入。

例如，考虑以下易受攻击的工作流：

```yaml
name: 易受攻击的工作流

on:
  pull_request_target

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: 获取 PR 编号
        id: pr-number
        run: |
          echo "PR_NUMBER=${{ github.event.pull_request.number }}" >> $GITHUB_ENV
      - name: 注入命令
        run: |
          # 用户控制的输入
          PR_NUMBER=${{ env.PR_NUMBER }}

          # 直接传递给 shell
          echo "Processing PR #$PR_NUMBER"

          # 易受攻击的命令执行
          ./deploy.sh --pr $PR_NUMBER
```

在上述示例中，攻击者可以通过将恶意payload注入到PR标题或描述中来执行任意命令。例如，如果攻击者创建一个标题为 `1; rm -rf /` 的PR，这将导致执行 `rm -rf /` 命令。

为了防止此类攻击，应该：

1. 验证和清理所有用户控制的输入
2. 使用安全的参数传递方法
3. 避免直接将用户输入传递给shell命令

## 参考资料

* [GitHub Actions 安全最佳实践](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions)
* [GitHub Actions 脚本注入防护](https://securitylab.github.com/research/github-actions-injections/)
* [OWASP GitHub Actions 安全指南](https://owasp.org/www-project-github-actions-security-top-10/)

### 权限提升

GitHub Actions 运行器默认具有与仓库相同的权限。在某些情况下，这可能导致权限提升，特别是当工作流使用敏感的 `secrets.GITHUB_TOKEN` 时。

考虑以下示例：

```yaml
name: 易受攻击的工作流

on:
  pull_request_target

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: 创建 PR 部署
        uses: actions/github-script@v5
        with:
          script: |
            // 攻击者可以修改此代码
            return await github.rest.repos.createDeployment({
                ...context.repo,
                ref: context.payload.pull_request.head.sha,
                auto_merge: false,
                required_contexts: [],
                environment: "production",
                transient_environment: false,
                production_environment: false,
            });
          github-token: ${{ secrets.GITHUB_TOKEN }}
```

在上述示例中，攻击者可以通过修改 `github-script` 来创建生产环境的部署，即使原始工作流只打算用于测试环境。

## 参考资料

* [GitHub Actions 权限管理](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions)
* [GitHub Actions Token 权限](https://docs.github.com/en/actions/security-guides/automatic-token-authentication)
* [GitHub Actions 安全最佳实践](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gitbook.cdxiaodong.life/cicd-an-quan/github-an-quan/actions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
