Skip to content
Open

cutting #8824

Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions apps/proxy/Caddyfile.aio.ce
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
{
{$CERT_EMAIL}
acme_ca {$CERT_ACME_CA:https://acme-v02.api.letsencrypt.org/directory}
{$CERT_ACME_DNS}
servers {
max_header_size 25MB
client_ip_headers X-Forwarded-For X-Real-IP
trusted_proxies static {$TRUSTED_PROXIES:0.0.0.0/0}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Security concern: overly permissive default for trusted_proxies.

Same issue as in Caddyfile.ce — the default 0.0.0.0/0 trusts all IP addresses for client IP header spoofing. Consider using private_ranges as the default.

Suggested fix
-		trusted_proxies static {$TRUSTED_PROXIES:0.0.0.0/0}
+		trusted_proxies static {$TRUSTED_PROXIES:private_ranges}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
trusted_proxies static {$TRUSTED_PROXIES:0.0.0.0/0}
trusted_proxies static {$TRUSTED_PROXIES:private_ranges}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/proxy/Caddyfile.aio.ce` at line 8, The Caddy config line setting
trusted_proxies uses an overly permissive default ("trusted_proxies static
{$TRUSTED_PROXIES:0.0.0.0/0}") which allows IP header spoofing; change the
default to use private_ranges instead so only RFC1918/local ranges are trusted.
Update the trusted_proxies declaration (the line referencing trusted_proxies and
the env var $TRUSTED_PROXIES) to default to private_ranges and ensure any
documentation or env examples reflect the new default.

}
}

(plane_proxy) {
request_body {
max_size {$FILE_SIZE_LIMIT}
Expand Down Expand Up @@ -30,17 +41,6 @@
}
}

{
{$CERT_EMAIL}
acme_ca {$CERT_ACME_CA:https://acme-v02.api.letsencrypt.org/directory}
{$CERT_ACME_DNS}
servers {
max_header_size 25MB
client_ip_headers X-Forwarded-For X-Real-IP
trusted_proxies static {$TRUSTED_PROXIES:0.0.0.0/0}
}
}

{$SITE_ADDRESS} {
import plane_proxy
}
64 changes: 31 additions & 33 deletions apps/proxy/Caddyfile.ce
Original file line number Diff line number Diff line change
@@ -1,39 +1,37 @@
(plane_proxy) {
request_body {
max_size {$FILE_SIZE_LIMIT}
}

redir /spaces /spaces/ permanent
reverse_proxy /spaces/* space:3000

redir /god-mode /god-mode/ permanent
reverse_proxy /god-mode/* admin:3000

reverse_proxy /live/* live:3000

reverse_proxy /api/* api:8000

reverse_proxy /auth/* api:8000

reverse_proxy /static/* api:8000

reverse_proxy /{$BUCKET_NAME}/* plane-minio:9000
reverse_proxy /{$BUCKET_NAME} plane-minio:9000

reverse_proxy /* web:3000
{
email {$CERT_EMAIL}
acme_ca {$CERT_ACME_CA:https://acme-v02.api.letsencrypt.org/directory}
# acme_dns {$CERT_ACME_DNS} # if Let's Encrypt

servers {
max_header_size 25MB
client_ip_headers X-Forwarded-For X-Real-IP
trusted_proxies static {$TRUSTED_PROXIES:0.0.0.0/0}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Security concern: overly permissive default for trusted_proxies.

The default value 0.0.0.0/0 trusts all IP addresses, allowing any client to spoof the X-Forwarded-For header. This can lead to incorrect client IP detection, bypassing of IP-based access controls, and audit log manipulation.

Consider using a more restrictive default such as private_ranges (which trusts only RFC 1918 private addresses) or requiring explicit configuration without a permissive fallback.

Suggested fix
-        trusted_proxies static {$TRUSTED_PROXIES:0.0.0.0/0}
+        trusted_proxies static {$TRUSTED_PROXIES:private_ranges}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
trusted_proxies static {$TRUSTED_PROXIES:0.0.0.0/0}
trusted_proxies static {$TRUSTED_PROXIES:private_ranges}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/proxy/Caddyfile.ce` at line 8, The Caddyfile sets trusted_proxies with
an overly permissive default ("trusted_proxies static
{$TRUSTED_PROXIES:0.0.0.0/0}"); change this to a restrictive default or require
explicit configuration by replacing the default value with a safer option such
as "private_ranges" or removing the permissive fallback so the variable must be
set; update the trusted_proxies line (referencing trusted_proxies and the
{$TRUSTED_PROXIES} variable) accordingly and add a comment or validation to
ensure deploys do not use a 0.0.0.0/0 default.

}
}

{
{$CERT_EMAIL}
acme_ca {$CERT_ACME_CA:https://acme-v02.api.letsencrypt.org/directory}
{$CERT_ACME_DNS}
servers {
max_header_size 25MB
client_ip_headers X-Forwarded-For X-Real-IP
trusted_proxies static {$TRUSTED_PROXIES:0.0.0.0/0}
}
(plane_proxy) {
request_body {
max_size {$FILE_SIZE_LIMIT}
}

redir /spaces /spaces/ permanent
reverse_proxy /spaces/* space:3000

redir /god-mode /god-mode/ permanent
reverse_proxy /god-mode/* admin:3000

reverse_proxy /live/* live:3000
reverse_proxy /api/* api:8000
reverse_proxy /auth/* api:8000
reverse_proxy /static/* api:8000

reverse_proxy /{$BUCKET_NAME}/* plane-minio:9000
reverse_proxy /{$BUCKET_NAME} plane-minio:9000

reverse_proxy /* web:3000
}

{$SITE_ADDRESS} {
import plane_proxy
import plane_proxy
}
255 changes: 255 additions & 0 deletions plane-app.backup_20260330_144144/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
x-db-env: &db-env
PGHOST: ${PGHOST:-plane-db}
PGDATABASE: ${PGDATABASE:-plane}
POSTGRES_USER: ${POSTGRES_USER:-plane}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-plane}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fail fast when required secrets are missing.

This stack currently boots with known defaults for the Postgres password, RabbitMQ password, MinIO access keys, DATABASE_URL, AMQP_URL, SECRET_KEY, and LIVE_SERVER_SECRET_KEY. Since the proxy later publishes 80/443, a missing or partial env file becomes a predictable-credential deployment instead of a hard failure.

Also applies to: 16-17, 21-22, 41-41, 47-47, 55-57, 60-60

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plane-app.backup_20260330_144144/docker-compose.yaml` at line 5, The compose
file currently supplies safe defaults for secrets (e.g., POSTGRES_PASSWORD,
RABBITMQ_DEFAULT_PASS, MINIO_ACCESS_KEY, MINIO_SECRET_KEY) and other critical
envs (DATABASE_URL, AMQP_URL, SECRET_KEY, LIVE_SERVER_SECRET_KEY), allowing
containers to start with predictable credentials; change each of those variable
interpolations to the "fail-fast" form so Docker Compose will error if they are
missing (use the shell-style parameter expansion that throws when unset, e.g.,
${VAR:?missing VAR}) for POSTGRES_PASSWORD, RABBITMQ_DEFAULT_PASS,
MINIO_ACCESS_KEY, MINIO_SECRET_KEY, DATABASE_URL, AMQP_URL, SECRET_KEY and
LIVE_SERVER_SECRET_KEY so the stack refuses to boot without explicit secrets.

POSTGRES_DB: ${POSTGRES_DB:-plane}
POSTGRES_PORT: ${POSTGRES_PORT:-5432}
PGDATA: ${PGDATA:-/var/lib/postgresql/data}

x-redis-env: &redis-env
REDIS_HOST: ${REDIS_HOST:-plane-redis}
REDIS_PORT: ${REDIS_PORT:-6379}
REDIS_URL: ${REDIS_URL:-redis://plane-redis:6379/}

x-minio-env: &minio-env
MINIO_ROOT_USER: ${AWS_ACCESS_KEY_ID:-access-key}
MINIO_ROOT_PASSWORD: ${AWS_SECRET_ACCESS_KEY:-secret-key}

x-aws-s3-env: &aws-s3-env
AWS_REGION: ${AWS_REGION:-}
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-access-key}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-secret-key}
AWS_S3_ENDPOINT_URL: ${AWS_S3_ENDPOINT_URL:-http://plane-minio:9000}
AWS_S3_BUCKET_NAME: ${AWS_S3_BUCKET_NAME:-uploads}

x-proxy-env: &proxy-env
APP_DOMAIN: ${APP_DOMAIN:-localhost}
FILE_SIZE_LIMIT: ${FILE_SIZE_LIMIT:-5242880}
CERT_EMAIL: ${CERT_EMAIL}
CERT_ACME_CA: ${CERT_ACME_CA}
CERT_ACME_DNS: ${CERT_ACME_DNS}
LISTEN_HTTP_PORT: ${LISTEN_HTTP_PORT:-80}
LISTEN_HTTPS_PORT: ${LISTEN_HTTPS_PORT:-443}
BUCKET_NAME: ${AWS_S3_BUCKET_NAME:-uploads}
SITE_ADDRESS: ${SITE_ADDRESS:-:80}

x-mq-env: &mq-env # RabbitMQ Settings
RABBITMQ_HOST: ${RABBITMQ_HOST:-plane-mq}
RABBITMQ_PORT: ${RABBITMQ_PORT:-5672}
RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER:-plane}
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD:-plane}
RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_VHOST:-plane}
RABBITMQ_VHOST: ${RABBITMQ_VHOST:-plane}

x-live-env: &live-env
API_BASE_URL: ${API_BASE_URL:-http://api:8000}
LIVE_SERVER_SECRET_KEY: ${LIVE_SERVER_SECRET_KEY:-2FiJk1U2aiVPEQtzLehYGlTSnTnrs7LW}

x-app-env: &app-env
WEB_URL: ${WEB_URL:-http://localhost}
DEBUG: ${DEBUG:-0}
CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS}
GUNICORN_WORKERS: 1
USE_MINIO: ${USE_MINIO:-1}
DATABASE_URL: ${DATABASE_URL:-postgresql://plane:plane@plane-db/plane}
SECRET_KEY: ${SECRET_KEY:-60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5}
AMQP_URL: ${AMQP_URL:-amqp://plane:plane@plane-mq:5672/plane}
API_KEY_RATE_LIMIT: ${API_KEY_RATE_LIMIT:-60/minute}
MINIO_ENDPOINT_SSL: ${MINIO_ENDPOINT_SSL:-0}
LIVE_SERVER_SECRET_KEY: ${LIVE_SERVER_SECRET_KEY:-2FiJk1U2aiVPEQtzLehYGlTSnTnrs7LW}

services:
web:
image: artifacts.plane.so/makeplane/plane-frontend:${APP_RELEASE:-v1.2.3}
deploy:
replicas: ${WEB_REPLICAS:-1}
restart_policy:
condition: any
Comment on lines +65 to +68
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect how the installer launches the stack.
fd -a '^setup\.sh$' .
rg -n -C2 'docker\s+(compose|stack)\s+' setup.sh

Repository: makeplane/plane

Length of output: 86


🏁 Script executed:

cat -n /home/jailuser/git/setup.sh

Repository: makeplane/plane

Length of output: 28021


🏁 Script executed:

cat -n plane-app.backup_20260330_144144/docker-compose.yaml | head -100

Repository: makeplane/plane

Length of output: 3971


🏁 Script executed:

rg -i 'docker\s+stack\s+deploy' --type sh --type yaml

Repository: makeplane/plane

Length of output: 152


🏁 Script executed:

grep -r "docker stack" . --include="*.md" --include="*.sh" --include="*.yaml" --include="*.yml" 2>/dev/null | head -20

Repository: makeplane/plane

Length of output: 393


Remove or relocate the deploy: configuration for Docker Compose deployments.

The standard installation path uses docker compose up -d (setup.sh), where deploy.replicas and deploy.restart_policy are ignored. These settings only apply to Docker Swarm mode (docker stack deploy), which has a separate deployment script at ./deployments/swarm/community/swarm.sh.

If supporting both deployment methods, consolidate the docker-compose.yaml into Compose-compatible configuration or maintain separate files. Otherwise, remove the deploy: sections and use Compose-specific options like restart_policy at the service level if restart behavior is needed.

This pattern affects multiple services across the file (web, space, admin, live, and likely others).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plane-app.backup_20260330_144144/docker-compose.yaml` around lines 65 - 68,
The compose file currently includes Docker Swarm-only fields (the deploy: block
with replicas and restart_policy) for services like web, space, admin, and live;
remove these deploy: sections from each service or relocate them into your
Swarm-specific manifest (./deployments/swarm/community/swarm.sh) and instead use
Compose-compatible options (e.g., add a service-level restart: unless-stopped or
restart: always) if restart behavior is required; ensure all occurrences of
deploy/replicas/restart_policy are cleaned up across the file or mirrored only
in the separate Swarm compose file so the top-level docker-compose.yaml is
Compose-compatible for docker compose up -d.

depends_on:
- api
- worker

space:
image: artifacts.plane.so/makeplane/plane-space:${APP_RELEASE:-v1.2.3}
deploy:
replicas: ${SPACE_REPLICAS:-1}
restart_policy:
condition: any
depends_on:
- api
- worker
- web

admin:
image: artifacts.plane.so/makeplane/plane-admin:${APP_RELEASE:-v1.2.3}
deploy:
replicas: ${ADMIN_REPLICAS:-1}
restart_policy:
condition: any
depends_on:
- api
- web

live:
image: artifacts.plane.so/makeplane/plane-live:${APP_RELEASE:-v1.2.3}
environment:
<<: [*live-env, *redis-env]
deploy:
replicas: ${LIVE_REPLICAS:-1}
restart_policy:
condition: any
depends_on:
- api
- web

api:
image: artifacts.plane.so/makeplane/plane-backend:${APP_RELEASE:-v1.2.3}
command: ./bin/docker-entrypoint-api.sh
deploy:
replicas: ${API_REPLICAS:-1}
restart_policy:
condition: any
volumes:
- logs_api:/code/plane/logs
environment:
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
depends_on:
- plane-db
- plane-redis
- plane-mq

worker:
image: artifacts.plane.so/makeplane/plane-backend:${APP_RELEASE:-v1.2.3}
command: ./bin/docker-entrypoint-worker.sh
deploy:
replicas: ${WORKER_REPLICAS:-1}
restart_policy:
condition: any
volumes:
- logs_worker:/code/plane/logs
environment:
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
depends_on:
- api
- plane-db
- plane-redis
- plane-mq

beat-worker:
image: artifacts.plane.so/makeplane/plane-backend:${APP_RELEASE:-v1.2.3}
command: ./bin/docker-entrypoint-beat.sh
deploy:
replicas: ${BEAT_WORKER_REPLICAS:-1}
restart_policy:
condition: any
volumes:
- logs_beat-worker:/code/plane/logs
environment:
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
depends_on:
- api
- plane-db
- plane-redis
- plane-mq

migrator:
image: artifacts.plane.so/makeplane/plane-backend:${APP_RELEASE:-v1.2.3}
command: ./bin/docker-entrypoint-migrator.sh
deploy:
replicas: 1
restart_policy:
condition: on-failure
volumes:
- logs_migrator:/code/plane/logs
environment:
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
depends_on:
- plane-db
- plane-redis

# Comment this if you already have a database running
plane-db:
Comment on lines +171 to +172
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

The “comment this out” guidance yields a broken external-service setup.

Line 171 says plane-db can be removed, but api, worker, beat-worker, and migrator still depend on plane-db, and earlier defaults still point PGHOST / DATABASE_URL at that hostname. Line 204 has the same problem for MinIO: removing plane-minio still leaves the app defaulting to USE_MINIO=1 and AWS_S3_ENDPOINT_URL=http://plane-minio:9000. This needs profiles/overrides or more explicit setup steps, not a one-line toggle.

Also applies to: 204-205

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plane-app.backup_20260330_144144/docker-compose.yaml` around lines 171 - 172,
The comment warns that simply removing the plane-db or plane-minio services
breaks other services because api, worker, beat-worker, and migrator still
depend on plane-db and environment defaults (PGHOST, DATABASE_URL, USE_MINIO,
AWS_S3_ENDPOINT_URL) point to plane-minio; fix by adding explicit docker-compose
profiles or override files and adjust service dependencies/envs: add a
"local-db" and "local-minio" profile or create docker-compose.override.yaml
examples that remove plane-db/plane-minio while updating
api/worker/beat-worker/migrator to not depend_on plane-db and to set
PGHOST/DATABASE_URL/USE_MINIO/AWS_S3_ENDPOINT_URL from external env variables
when those profiles are disabled; alternatively change the top-level comments to
instruct users to set PGHOST/DATABASE_URL and USE_MINIO/AWS_S3_ENDPOINT_URL when
they remove plane-db/plane-minio and show a sample env or override file.

image: postgres:15.7-alpine
command: postgres -c 'max_connections=1000'
deploy:
replicas: 1
restart_policy:
condition: any
environment:
<<: *db-env
volumes:
- pgdata:/var/lib/postgresql/data

plane-redis:
image: valkey/valkey:7.2.11-alpine
deploy:
replicas: 1
restart_policy:
condition: any
volumes:
- redisdata:/data

plane-mq:
image: rabbitmq:3.13.6-management-alpine
deploy:
replicas: 1
restart_policy:
condition: any
environment:
<<: *mq-env
volumes:
- rabbitmq_data:/var/lib/rabbitmq

# Comment this if you using any external s3 compatible storage
plane-minio:
image: minio/minio:latest
command: server /export --console-address ":9090"
deploy:
replicas: 1
restart_policy:
condition: any
environment:
<<: *minio-env
volumes:
- uploads:/export

# Comment this if you already have a reverse proxy running
proxy:
image: artifacts.plane.so/makeplane/plane-proxy:${APP_RELEASE:-v1.2.3}
deploy:
replicas: 1
restart_policy:
condition: any
environment:
<<: *proxy-env
ports:
- target: 80
published: ${LISTEN_HTTP_PORT:-80}
protocol: tcp
mode: host
- target: 443
published: ${LISTEN_HTTPS_PORT:-443}
protocol: tcp
mode: host
volumes:
- proxy_config:/config
- proxy_data:/data
depends_on:
- web
- api
- space
- admin
- live

volumes:
pgdata:
redisdata:
uploads:
logs_api:
logs_worker:
logs_beat-worker:
logs_migrator:
rabbitmq_data:
proxy_config:
proxy_data:
Comment on lines +1 to +255
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove the timestamped backup compose file from the repo.

setup.sh:5-20 points the installer at plane-app/docker-compose.yaml, and setup.sh:588-603 only backs up runtime data under plane-app/backup/.... This plane-app.backup_20260330_144144/ copy looks like a local snapshot rather than an installer-managed artifact, so keeping it checked in creates a second deployment definition that will drift.

🧰 Tools
🪛 Checkov (3.2.510)

[medium] 193-194: Basic Auth Credentials

(CKV_SECRET_4)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plane-app.backup_20260330_144144/docker-compose.yaml` around lines 1 - 255,
This committed timestamped backup compose
(plane-app.backup_20260330_144144/docker-compose.yaml) must be removed — delete
that backup directory and file from the repository, add a rule to .gitignore to
prevent committing timestamped backup folders (e.g., plane-app.backup_*), and
ensure the installer references the canonical compose (the setup.sh usage of
plane-app/docker-compose.yaml remains unchanged); commit the deletion and
.gitignore update so only the single deployment definition is tracked.

Loading