Skip to content
7 min read·Lesson 8 of 8

Security Hardening and OIDC for Cloud Deployments

Lock down GitHub Actions: minimum permissions, pinned actions, OpenID Connect to AWS/Azure/GCP, and CodeQL/secret scanning.

GitHub Actions has access to your code, your build artifacts, and — through secrets — your cloud accounts. A poorly secured workflow is a credential leak waiting to happen. This lesson covers the seven hardening practices every team should adopt.

1. Lock Down GITHUB_TOKEN Permissions

Every workflow run is given a token with permissions to the repo's resources. Make it read-only by default and grant per-job:

permissions: read-all       # workflow default

jobs:
  release:
    permissions:
      contents: write       # tag and publish a release
      pull-requests: write  # comment on PRs
    runs-on: ubuntu-latest
    steps: [...]

You can also set the default for the whole org at Org Settings → Actions → General → Workflow permissions. Set "Read repository contents and packages permissions" and require workflows to explicitly opt in to write scopes.

2. Pin Actions by SHA

Branch refs like @main on third-party actions are a supply-chain risk — the maintainer (or an attacker who compromises them) can push code that runs in your context.

- uses: hashicorp/setup-terraform@b9cd5d3eea4d0e02e1e80fb0ff5a6b95f6b0a5e0  # v3.1.2

Use Dependabot's github-actions ecosystem to keep pinned SHAs updated via reviewable PRs.

3. OIDC: Stop Storing Cloud Keys

OpenID Connect lets your workflow request a short-lived token signed by GitHub. AWS, Azure, GCP, HashiCorp Vault, and many other services trust GitHub's OIDC provider directly. The flow:

  1. Configure the cloud provider to trust GitHub's OIDC issuer (token.actions.githubusercontent.com)
  2. Create a role/identity bound to specific repo + branch + workflow claims
  3. Your workflow requests an OIDC token and exchanges it for cloud credentials
  4. The credentials are valid for the duration of the job — typically 60 minutes

AWS example

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write     # required for OIDC
      contents: read
    steps:
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/gha-deploy
          aws-region: us-east-1
      - run: aws sts get-caller-identity

The IAM role's trust policy restricts which repo and branch can assume it — typically scoped to repo:acme/my-app:ref:refs/heads/main. No stored AWS keys; no key rotation; no leakage risk.

Azure / GCP

Azure: azure/login@v2 with federated-credential-configuration. GCP: google-github-actions/auth@v2 with workload identity federation. All three clouds support the same pattern.

4. Protect Workflow Files Themselves

A workflow file is executable infrastructure. Add it to CODEOWNERS and require reviews from a security team:

# .github/CODEOWNERS
/.github/workflows/      @acme/devops-security

Combined with branch protection requiring CODEOWNERS review, this prevents drive-by workflow changes.

5. Be Careful with pull_request_target

The pull_request trigger runs PRs without repo secrets — by design, because fork PRs shouldn't see your AWS key. The pull_request_target trigger runs with secrets, in the context of the base branch. It is a dangerous primitive — if the workflow checks out the PR's code and runs it, an attacker's PR can exfiltrate your secrets.

Rule: if you use pull_request_target, never check out the PR's code unless you also restrict the workflow to label/comment-driven invocation by maintainers.

6. Secret Scanning and Push Protection

GitHub Advanced Security (GHAS) — included free for public repos, paid for private — scans pushed code for credentials. Push Protection rejects pushes containing known credential formats before they enter the repo. Enable both:

  • Settings → Code security and analysis → Secret scanning: Enabled
  • Settings → Code security and analysis → Push protection: Enabled

Hundreds of credential patterns from partners (AWS, Stripe, Twilio, etc.) are recognised.

7. Code Scanning (CodeQL)

CodeQL is GitHub's semantic code analysis engine. Enable it via the default setup:

name: CodeQL
on:
  push: { branches: [main] }
  pull_request: { branches: [main] }
  schedule: [{ cron: '0 6 * * 1' }]

jobs:
  analyze:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
      contents: read
    strategy:
      matrix:
        language: [javascript, python]
    steps:
      - uses: actions/checkout@v4
      - uses: github/codeql-action/init@v3
        with: { languages: ${{ matrix.language }} }
      - uses: github/codeql-action/autobuild@v3
      - uses: github/codeql-action/analyze@v3

Findings appear in the Security tab. The GH-300 exam covers this in detail.

8. Dependency Review

- uses: actions/dependency-review-action@v4
  with:
    fail-on-severity: high
    allow-licenses: MIT, Apache-2.0, BSD-3-Clause

On PRs that change dependencies, this action blocks the merge if the diff introduces high-severity CVEs or disallowed licences.

Defence-in-Depth Checklist

ControlWhere
Read-only default GITHUB_TOKENOrg/Repo settings
Workflow approvals from outside collaboratorsOrg/Repo settings
Pinned third-party actionsWorkflow YAML
OIDC for cloud deploysWorkflow YAML + cloud IAM
CODEOWNERS on .github/workflowsRepo
Required reviews on protected branchesBranch protection rules
Secret scanning + push protectionRepo / Org
CodeQL on PRsWorkflow
Dependency review on PRsWorkflow
Environments with required reviewers for prodRepo environments

Adopt these incrementally — even just steps 1, 2, and 3 dramatically shrink the blast radius of a CI/CD compromise.

Where to Go Next

To go deeper, take the GH-200 (Actions) exam first, then the GH-300 (Advanced Security) exam. The GH-300 blueprint covers CodeQL, secret scanning, supply-chain attestations (SLSA), and Dependabot — all of which build on the foundation you have now.

Key Takeaways

  • Default GITHUB_TOKEN to read-only, then grant per-job permissions as needed.
  • Pin third-party actions to a commit SHA — Dependabot can keep them updated safely.
  • OIDC eliminates the need to store long-lived cloud credentials in GitHub secrets.
  • CODEOWNERS plus required reviews on workflow files prevents unauthorised pipeline changes.
  • GitHub Advanced Security adds secret scanning, code scanning (CodeQL), and dependency review.
🎉

Course Complete!

You've finished GitHub Actions & Workflows. Now put your knowledge to the test with real exam-style practice questions.