
## 引言
而家個個都用 CI/CD pipeline 嚟 deploy,但你有冇諗過,你條 GitHub Actions pipeline 本身都可能係攻擊者嘅入口?GitHub Actions 作為最流行嘅 CI/CD 平台,每日有數以百萬計嘅 workflow 執行,但好多人 set 完就唔理安全設定,結果搞到成個 repo、甚至成個 organisation 嘅 secrets 都俾人偷曬。
今日就同大家深入講解 GitHub Actions 安全最佳實踐,由 secrets 管理、權限控制、到 workflow 審計,逐個 step 教你點樣鎖實你嘅 CI/CD pipeline。
## GitHub Actions 安全:點解你要關心?
GitHub Actions 嘅設計理念係方便同靈活,但靈活嘅另一面就係風險。以下係幾個真實發生過嘅安全問題:
– **Secrets 洩漏** — workflow log 唔小心 print 咗 secrets 出嚟,全世界都睇到
– **Pull Request 攻擊** — 惡意 contributor 喺 PR 入面改 workflow file,偷走 repository secrets
– **供應鏈攻擊** — 用咗來歷不明嘅 third-party action,暗中偷 secrets 或 inject 惡意 code
– **過度權限** — workflow 嘅 GITHUB_TOKEN 有 write 權限,但其實只需要 read
以下我會逐一教你點樣防範。
## GitHub Actions 安全:Secrets 管理
Secrets 係 GitHub Actions 入面最敏感嘅嘢。API keys、deployment tokens、cloud credentials 全部都放喺 secrets 度。一個唔小心 expose 咗,成個 infrastructure 都可以俾人 hijack。
### ✅ 基本規則
**絕不直接 hardcode secrets 喺 workflow YAML**
❌ 錯:
env:
AWS_ACCESS_KEY_ID: AKIAIOSFODNN7EXAMPLE
✅ 啱:
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
### ✅ 限制 secrets 嘅 scope
GitHub Actions 支援 environment-level secrets,你可以將 production secrets 同 staging secrets 分開:
jobs:
deploy:
runs-on: ubuntu-latest
environment: production # 只用 production environment 嘅 secrets
steps:
- run: ./deploy.sh
Environment secrets 仲可以加 approval gates — 例如 production environment 要特定 reviewer approve 先可以行,等於多一層人手把關。
### ✅ 避免 secrets 出現喺 logs
GitHub Actions 會自動 mask secrets 值,用 `***` 代替。但呢個機制有漏洞 — 如果 secrets 值經過 encoding 或 transformation,masking 未必 work。
❌ 危險:
echo "Deploying with token: ${{ secrets.DEPLOY_TOKEN }}" # token 可能部分 leakage
✅ 安全:
echo "Deploying..." # 完全唔提及 secrets
${{ secrets.DEPLOY_TOKEN }} | ./auth-script.sh # 直接 pipe 俾 script
另外,GitHub Actions 亦支援 `::add-mask::` command 手動 mask 動態產生嘅 secrets。
## GitHub Actions 安全:Pull Request 防禦
呢個係最常見嘅攻擊 vector。當有人 submit PR,PR 入面嘅 workflow 改動可能會:
1. 修改 workflow trigger,令惡意 code 喺 push 時執行
2. 加一個 step 偷走 secrets 然後 curl 去 attacker server
### ✅ 用 pull_request_target 要極度小心
`pull_request_target` event 會用 target repository 嘅 context 執行(即係有權限 access secrets),但同時會 checkout PR 嘅 code。呢個組合極之危險。
❌ 絕不應該咁做:
on:
pull_request_target
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }} # Checkout PR code!
- run: npm test # 行 PR code 但有 secrets access!
✅ 如果真係要用 `pull_request_target`,必須:
– 永遠 checkout default branch,唔好 checkout PR code
– 唔好執行任何來自 PR 嘅 script
– 手動 review 所有 code 改動先 approve workflow run
### ✅ 限制 GITHUB_TOKEN 權限
Default GITHUB_TOKEN 嘅權限太闊,建議喺 workflow level 或 job level 限制:
permissions:
contents: read
pull-requests: write
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
咁樣就算 attacker 偷到 GITHUB_TOKEN,都只係有 read contents 權限,唔能夠改 code 或 merge PR。
## GitHub Actions 安全:Third-Party Action 審查
GitHub Marketplace 有過萬個 actions,但你點知邊個安全邊個唔安全?
### ✅ 永遠 pin 到 commit SHA
❌ 用 version tag(可以俾人改):
- uses: actions/checkout@v4
✅ Pin 到 immutable commit SHA:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
Version tag 係 mutable — action maintainer 可以 force push 改 tag,指去另一個 commit。Commit SHA 係 immutable,冇人可以改。
### ✅ 審查 action 權限
每個 action 都有自己嘅 `action.yml`,入面定義咗佢需要咩 permission。揀 action 之前:
– 睇 source code(唔好只用 pre-built docker image)
– 檢查佢 access 咗咩 environment variables
– 睇下有冇 network call(curl 去 external server)
– 用 GitHub 嘅 “Verified creator” badge 做初步篩選
### ✅ 用 allowlist 限制允許嘅 actions
如果你係 organisation owner,可以用 GitHub 嘅 “Allow specified actions” 設定:
Organization Settings → Actions → General → Actions permissions
→ Allow enterprise, and select non-enterprise, actions and reusable workflows
咁樣只允許 GitHub 官方 actions + verified creators,block 曬其他來歷不明嘅 actions。
## GitHub Actions 安全:Workflow 審計與監控
### ✅ 啟用 audit logging
GitHub Enterprise 提供 audit log API,可以 track 所有 workflow 執行記錄:
# 用 GitHub CLI 查 workflow run history
gh api repos/your-org/your-repo/actions/runs --jq '.workflow_runs[] | {name: .name, conclusion: .conclusion, event: .event}'
### ✅ 設定 branch protection rules
確保重要 branch(main / production)有 protection:
Settings → Branches → Branch protection rules → Add rule
✅ Require a pull request before merging
✅ Require status checks to pass before merging
✅ Require conversation resolution before merging
✅ Do not allow bypassing the above settings
另外,可以要求特定 workflow 通過先可以 merge(例如全部 test pass、security scan pass 等)。
### ✅ 用 OIDC 代替 long-lived secrets
傳統做法係放 cloud provider 嘅 API key 入 GitHub Secrets,但呢啲 key 係 long-lived,一旦 leak 就好大鑊。
OIDC (OpenID Connect) 令 GitHub Actions 可以動態拎短期 token:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-role
aws-region: ap-east-1
唔使再放 AWS_ACCESS_KEY_ID 入 secrets — GitHub Actions 會用 OIDC token 同 AWS 交換短期 credentials,自動過期。
## 實戰 Checklist
以下係一個快速 checklist,每次開新 repo 或 review 現有 pipeline 都用得着:
– [ ] GITHUB_TOKEN permissions 設為最細權限(read-only by default)
– [ ] 所有 secrets 用 `${{ secrets.X }}` 引用,冇 hardcode
– [ ] Production environment 啟用 approval gate
– [ ] Pull request workflow 唔會 checkout untrusted code
– [ ] 所有 third-party actions pin 到 commit SHA
– [ ] 用 OIDC 代替 long-lived cloud credentials
– [ ] Branch protection rules 已啟用
– [ ] Audit logging 已啟用(如有 GitHub Enterprise)
## 結語
GitHub Actions 安全唔係一次性嘅工作,而係持續嘅過程。每次改 workflow、加新 action、改 secrets、都要諗一諗:「呢個改動會唔會開咗個安全漏洞?」
記住一個原則:**Least Privilege**。Workflow 只需要最小嘅權限去做佢要做嘅嘢,多咗嘅權限就係多咗嘅風險。
🔗 參考資料:NVD NIST 漏洞資料庫
CI/CD 安全係 DevSecOps 嘅核心,做好咗,你先真正享受到自動化帶來嘅效率提升,而唔係自動化帶來嘅安全災難。
#GitHubActions #CICDSecurity #DevSecOps #GitHub安全 #CI/CD安全



