Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Integrity Rules (700s)

Integrity rules cover secret exposure, credential leakage, command safety, and Docker image pinning. These rules ensure that workflow configurations do not inadvertently compromise secrets or weaken the build pipeline.


WRD-701: toJSON Secrets Exposure

Severity: Critical

What it detects: toJSON(secrets) or secrets.* patterns that expose the entire secrets context. If this value reaches logs, artifacts, or outputs, all repository secrets are compromised.

Vulnerable:

- run: echo '${{ toJSON(secrets) }}'

Remediation: Reference individual secrets by name (e.g., secrets.MY_TOKEN) instead of dumping the entire secrets context.


WRD-710: Artipacked

Severity: High

What it detects: actions/checkout without persist-credentials: false in workflows that also upload artifacts. When persist-credentials is true (the default), the GITHUB_TOKEN is stored in .git/config. If the .git directory is included in an uploaded artifact, the token can be extracted.

Vulnerable:

- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
  # persist-credentials defaults to true
- run: make build
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
  with:
    name: build-output
    path: .

Remediation: Add persist-credentials: false to the checkout step, or ensure the .git directory is excluded from uploaded artifacts.

- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
  with:
    persist-credentials: false

WRD-711: Secrets Inherit

Severity: High

What it detects: secrets: inherit in reusable workflow calls, which passes every secret in the calling repository to the called workflow. If that workflow is external or broadly scoped, secrets may be exposed unnecessarily.

Vulnerable:

jobs:
  build:
    uses: some-org/shared/.github/workflows/build.yml@main
    secrets: inherit

Remediation: Pass only the specific secrets the called workflow needs.

jobs:
  build:
    uses: some-org/shared/.github/workflows/build.yml@main
    secrets:
      npm-token: ${{ secrets.NPM_TOKEN }}

WRD-712: Insecure Commands

Severity: High

What it detects: ACTIONS_ALLOW_UNSECURE_COMMANDS set to true, which re-enables the deprecated set-env and add-path workflow commands. These legacy commands are vulnerable to injection attacks via untrusted input.

Vulnerable:

env:
  ACTIONS_ALLOW_UNSECURE_COMMANDS: true

Remediation: Remove ACTIONS_ALLOW_UNSECURE_COMMANDS and use GITHUB_ENV / GITHUB_PATH files instead of the legacy commands.


WRD-713: Hardcoded Credentials

Severity: High

What it detects: Hardcoded username or password values in container/services credentials blocks instead of secret references. This exposes credentials in the workflow file.

Vulnerable:

jobs:
  test:
    services:
      db:
        image: postgres
        credentials:
          username: admin
          password: supersecret123

Remediation: Use secret references for credentials.

credentials:
  username: ${{ secrets.REGISTRY_USERNAME }}
  password: ${{ secrets.REGISTRY_PASSWORD }}

WRD-714: Curl Pipe Bash

Severity: High

What it detects: curl | bash, wget | sh, and similar patterns that download and immediately execute remote scripts in run: blocks. A compromised server or MITM attack could inject malicious code.

Vulnerable:

- run: curl https://get.example.com/install.sh | bash

Remediation: Download the script first, verify its checksum or signature, then execute.

- run: |
    curl -Lo install.sh https://get.example.com/install.sh
    echo "expectedsha256sum  install.sh" | sha256sum -c
    bash install.sh

WRD-720: Unpinned Docker Images

Severity: Medium

What it detects: Container or services image: references that are not pinned to a specific @sha256: digest. Docker image tags are mutable and can be replaced with compromised versions.

Vulnerable:

jobs:
  test:
    container:
      image: node:18
    services:
      redis:
        image: redis:7

Remediation: Pin images to a sha256 digest.

container:
  image: node:18@sha256:a1b2c3d4e5f6...