Dangerous Triggers Rule (Medium)

Dangerous Triggers Rule (Medium) Overview #

The dangerous-triggers-medium rule detects workflows using privileged triggers (pull_request_target, workflow_run, issue_comment, etc.) with only partial security mitigations. While some protections exist, additional mitigations are recommended for defense in depth.

Rule ID #

dangerous-triggers-medium

Security Impact #

Severity: Medium

This rule triggers when a workflow has:

  • Privileged triggers that grant elevated permissions
  • Some mitigations in place (score 1-2)
  • Missing recommended additional protections

When This Rule Triggers #

The rule uses a scoring system to evaluate mitigations:

MitigationPointsDescription
Permissions Restriction+3permissions: read-all or permissions: {}
Environment Protection+2Using protected environments with approval
Label Condition+1Checking for approved labels
Actor Restriction+1Checking github.actor
Fork Check+1Checking github.event.pull_request.head.repo.fork

Medium severity is reported when the total score is 1-2 points.

Example Partially Mitigated Workflow #

name: PR Processor

on:
  pull_request_target:
    types: [labeled]

jobs:
  process:
    runs-on: ubuntu-latest
    # PARTIAL: Only has label check (+1 point)
    if: contains(github.event.pull_request.labels.*.name, 'safe-to-run')
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}
      - run: ./process.sh

Detection Output:

$ sisakulint .github/workflows/process.yaml

.github/workflows/process.yaml:3:3: dangerous trigger (medium): workflow uses privileged trigger(s) [pull_request_target] with partial mitigations (label condition). Consider adding more mitigations for defense in depth: restrict permissions (permissions: read-all), use environment protection, add label conditions, or check github.actor. See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ [dangerous-triggers-medium]

How to Improve #

Add Permissions Restriction #

The most impactful improvement is adding explicit permissions:

name: PR Processor

on:
  pull_request_target:
    types: [labeled]

# ADD: Explicit permissions (+3 points)
permissions:
  contents: read
  pull-requests: write

jobs:
  process:
    runs-on: ubuntu-latest
    if: contains(github.event.pull_request.labels.*.name, 'safe-to-run')
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}
      - run: ./process.sh

Add Environment Protection #

For sensitive operations, add environment protection:

name: PR Processor

on:
  pull_request_target:
    types: [labeled]

jobs:
  process:
    runs-on: ubuntu-latest
    # ADD: Environment protection (+2 points)
    environment: pr-processing
    if: contains(github.event.pull_request.labels.*.name, 'safe-to-run')
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}
      - run: ./process.sh

Combine Multiple Mitigations (Best Practice) #

For maximum security, combine multiple mitigations:

name: Secure PR Processor

on:
  pull_request_target:
    types: [labeled]

# Mitigation 1: Permissions (+3 points)
permissions:
  contents: read

jobs:
  process:
    runs-on: ubuntu-latest
    # Mitigation 2: Environment (+2 points)
    environment: pr-processing
    # Mitigation 3: Label + Fork check (+2 points)
    if: |
      contains(github.event.pull_request.labels.*.name, 'safe-to-run') &&
      github.event.pull_request.head.repo.fork == false
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}
      - run: ./process.sh

This workflow has a score of 7 points - well above the acceptable threshold.

Auto-Fix Support #

The rule provides automatic fixes by adding permissions: {} if permissions are not already restricted:

# Preview changes
sisakulint -fix dry-run

# Apply fixes
sisakulint -fix on

Mitigation Strategies Comparison #

StrategyPointsProsCons
permissions: read-all+3Simple, effectiveMay break legitimate writes
permissions: {}+3Maximum restrictionMay need explicit permissions
Environment Protection+2Requires approvalAdds latency
Label Condition+1Easy to implementCan be bypassed if maintainer adds label
Actor Check+1Good for specific usersRequires maintenance
Fork Check+1Prevents fork attacksBlocks legitimate fork contributions

Common Patterns That Trigger Medium #

  1. Only Label Check

    if: contains(github.event.pull_request.labels.*.name, 'approved')
    

    Score: 1 point - needs more mitigations

  2. Only Environment Protection

    environment: production
    

    Score: 2 points - needs more mitigations

  3. Actor + Label but No Permissions

    if: github.actor == 'dependabot[bot]' && contains(...)
    

    Score: 2 points - add permissions restriction

Difference from Critical Severity #

AspectCriticalMedium
Score01-2
MitigationsNonePartial
RiskImmediate exploitationReduced but present
Auto-fixAlways appliedApplied if no permissions
RecommendationMust fix immediatelyImprove for defense in depth

References #

favicon

securitylab.github.com

Secure use reference - GitHub Docs

favicon

docs.github.com

OWASP Top 10 CI/CD Security Risks | OWASP Foundation

OWASP Top 10 CI/CD Security Risks project helps defenders identify focus areas for securing their CI/CD ecosystem.

favicon

owasp.org