Skip to content

fix: allow docker compose command chaining - #4997

Open
ews-pgasser wants to merge 4 commits into
Dokploy:canaryfrom
ews-pgasser:fix/chaining-canary
Open

fix: allow docker compose command chaining#4997
ews-pgasser wants to merge 4 commits into
Dokploy:canaryfrom
ews-pgasser:fix/chaining-canary

Conversation

@ews-pgasser

@ews-pgasser ews-pgasser commented Aug 6, 2026

Copy link
Copy Markdown

What is this PR about?

This PR updates the sanitizeCommand logic to safely allow && chaining in custom compose deployment commands. Currently, the strict blocklist on & prevents users from executing standard multi-step deployments (such as compose pull && docker compose down && docker compose up -d --build). This is critical for stacks that require full teardowns to clear in-memory caches (e.g., Redis) or sync volume mounts during image updates. The updated logic blocks single & (backgrounding) and strictly enforces that any chained command must securely start with docker compose or docker-compose , maintaining security while unblocking legitimate DevOps workflows.

Checklist

Before submitting this PR, please make sure that:

  • You created a dedicated branch based on the canary branch.
  • You have read the suggestions in the CONTRIBUTING.md file https://github.com/Dokploy/dokploy/blob/canary/CONTRIBUTING.md#pull-request
  • You have tested this PR in your local instance. If you have not tested it yet, please do so before submitting. This helps avoid wasting maintainers' time reviewing code that has not been verified by you.

Issues related (if applicable)

closes #4992

Screenshots (if applicable)

Greptile Summary

This PR permits guarded && chaining in custom Docker Compose deployment commands while continuing to reject unsafe shell metacharacters and non-Compose chain segments.

  • Adds validation for paired ampersands and Compose-only chained commands.
  • Adds focused acceptance and rejection tests for the new command grammar.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Reviews (3): Last reviewed commit: "chore: add tests" | Re-trigger Greptile

Context used:

@dosubot dosubot Bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Aug 6, 2026
Comment thread packages/server/src/utils/builders/compose.ts Outdated
@ews-pgasser

Copy link
Copy Markdown
Author

@Siumauricio @narcisonunez please check this PR, we urgently need the docker compose command chaining feature back and there is no possibility to downgrade versions too.

@narcisonunez

Copy link
Copy Markdown
Collaborator

@ews-pgasser

Add tests (compose-command-injection.test.ts)
Run Biome check

@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:S This PR changes 10-29 lines, ignoring generated files. labels Aug 7, 2026
@ews-pgasser

ews-pgasser commented Aug 7, 2026

Copy link
Copy Markdown
Author

@ews-pgasser

Add tests (compose-command-injection.test.ts) Run Biome check

✅ done, both succeded properly @narcisonunez


Biome Check (node_modules/.bin/biome check packages/server/src/utils/builders/compose.ts apps/dokploy/__test__/compose/compose-command-injection.test.ts)

Checked 2 files in 8ms. No fixes applied.

Tests (pnpm vitest run --config __test__/vitest.config.ts __test__/compose/compose-command-injection.test.ts)

 ✓ __test__/compose/compose-command-injection.test.ts (13 tests) 43ms
   ✓ compose createCommand injection (13)
     ✓ escapes composePath (docker-compose) 15ms
     ✓ escapes composePath (stack deploy) 10ms
     ✓ escapes appName 10ms
     ✓ rejects a custom command containing shell control characters 2ms
     ✓ allows a legitimate custom command 0ms
     ✓ keeps a legitimate composePath intact 2ms
     ✓ allows chained docker compose commands with '&&' 0ms
     ✓ allows chaining with the legacy 'docker-compose' spelling 0ms
     ✓ rejects a single '&' used for backgrounding 0ms
     ✓ rejects a malformed '&&&' chain 0ms
     ✓ rejects chained segments that are not docker compose invocations 0ms
     ✓ rejects an attempted injection smuggled inside a chained segment 0ms
     ✓ rejects a chain that only pretends to start with docker compose later in the string 0ms
 Test Files  1 passed (1)
      Tests  13 passed (13)
   Start at  11:57:57
   Duration  3.45s (transform 991ms, setup 56ms, import 3.22s, tests 43ms, environment 0ms)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docker-compose redeploys leave stale containers/orphans instead of cleanly recreating the stack

2 participants