Skip to content

feat(database-credentials): add password update functionality for Mar…#4144

Merged
Siumauricio merged 6 commits intocanaryfrom
4041-add-ability-to-change-services-password-like-mysql-and-whatnot
Apr 4, 2026
Merged

feat(database-credentials): add password update functionality for Mar…#4144
Siumauricio merged 6 commits intocanaryfrom
4041-add-ability-to-change-services-password-like-mysql-and-whatnot

Conversation

@Siumauricio
Copy link
Copy Markdown
Contributor

@Siumauricio Siumauricio commented Apr 4, 2026

…iaDB, MongoDB, MySQL, Postgres, and Redis

  • Introduced a new UpdateDatabasePassword component to facilitate password updates for database credentials.
  • Implemented password change mutations in the respective API routers for MariaDB, MongoDB, MySQL, Postgres, and Redis.
  • Enhanced user experience by providing success notifications upon successful password updates.
  • Updated UI components to include the new password update functionality, ensuring consistency across different database types.

What is this PR about?

Please describe in a short paragraph what this PR is about.

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 #4041 #933

Screenshots (if applicable)

Greptile Summary

This PR adds a live password-update feature for all five database types (MariaDB, MongoDB, MySQL, Postgres, Redis). A new shared UpdateDatabasePassword dialog component collects the new password, calls a per-database changePassword tRPC mutation, and invalidates the query cache on success. Each mutation shells out to the running container via docker exec to change the password at the DB level, then persists the new value in Dokploy's own store.

The UI integration and the overall flow are well-structured, but the server-side implementations have critical security and correctness issues that need to be resolved before merging:

  • Shell injection (P0) — All five routers interpolate the user-supplied password directly into single-quoted shell strings without any escaping. A password containing a shell metacharacter would break out of the quoted context, potentially executing arbitrary commands on the host. This affects postgres.ts, mysql.ts, mariadb.ts, mongo.ts, and redis.ts.
  • Dead-code ternary in mysql.ts (P1)authPassword is computed with a ternary where both branches evaluate to databaseRootPassword, making the conditional pointless and the code misleading.
  • No password-confirmation field (P2) — The UpdateDatabasePassword dialog accepts only a single password input. A typo will silently lock the database. Adding a confirmation field with a Zod refine check would prevent accidental lockouts.

Confidence Score: 1/5

Not safe to merge — the shell injection vulnerability allows an attacker who can set a database password to execute arbitrary commands on the host.

All five new server-side mutations contain a shell injection vulnerability that lets a crafted password break out of the single-quoted shell string and run arbitrary commands on the host. This is a critical security issue. There is also a dead-code ternary bug in mysql.ts and a minor UX gap in the shared component. These issues must be resolved before the PR is merged.

All five router files (postgres.ts, mysql.ts, mariadb.ts, mongo.ts, redis.ts) need the shell injection fixed. mysql.ts also needs the dead-code ternary removed.

Reviews (1): Last reviewed commit: "[autofix.ci] apply automated fixes" | Re-trigger Greptile

Greptile also left 4 inline comments on this PR.

…iaDB, MongoDB, MySQL, Postgres, and Redis

- Introduced a new `UpdateDatabasePassword` component to facilitate password updates for database credentials.
- Implemented password change mutations in the respective API routers for MariaDB, MongoDB, MySQL, Postgres, and Redis.
- Enhanced user experience by providing success notifications upon successful password updates.
- Updated UI components to include the new password update functionality, ensuring consistency across different database types.
@Siumauricio Siumauricio linked an issue Apr 4, 2026 that may be closed by this pull request
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Apr 4, 2026
@dosubot dosubot bot added the enhancement New feature or request label Apr 4, 2026
echo "No running container found for ${appName}" >&2
exit 1
fi
docker exec "$CONTAINER_ID" redis-cli -a '${databasePassword}' CONFIG SET requirepass '${password}'
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.

P0 Shell injection via both databasePassword and password

Both the existing password (used for -a '${databasePassword}' authentication) and the new password ('${password}') are interpolated without escaping. A password containing a single quote will break out of the single-quoted shell context. Additionally, using -a to pass the password on the command line will cause Redis to print a deprecation warning; REDISCLI_AUTH env var or --pass via stdin is preferred, but more importantly the values must not be shell-interpolated raw.

Comment on lines +419 to +426
const command = `
CONTAINER_ID=$(${containerCmd})
if [ -z "$CONTAINER_ID" ]; then
echo "No running container found for ${appName}" >&2
exit 1
fi
docker exec "$CONTAINER_ID" psql -U ${databaseUser} -c "ALTER USER \\"${databaseUser}\\" WITH PASSWORD '${password}';"
`;
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.

P0 Shell injection via unsanitised password interpolation

The password value (and databaseUser) are interpolated directly into a shell string using single-quote delimiters. A password that contains a single-quote character will prematurely terminate the shell string, allowing an attacker to inject and execute arbitrary shell commands on the host running the container.

The same issue exists in the equivalent changePassword mutations in mariadb.ts (~line 400), mongo.ts (~line 419), mysql.ts (~line 421), and redis.ts (~line 406) — all five routers are affected.

The recommended remediation is to avoid interpolating secrets into shell strings at all. One approach is to write the sensitive value to a file or pipe it inside the container via docker exec -i, so it is never part of the evaluated shell string. At a minimum, single-quote characters in any interpolated value must be escaped before embedding in a single-quoted shell argument.

Comment on lines +411 to +412
const authPassword =
type === "root" ? databaseRootPassword : databaseRootPassword;
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.

P1 Dead-code ternary — both branches are identical

Both arms of the ternary expression evaluate to databaseRootPassword, so authPassword is always the root password regardless of type. Using root credentials to authenticate is actually correct (root is required to run ALTER USER for any MySQL account), but the ternary is misleading dead code — databasePassword is never even destructured from my.

Simplify to a direct assignment to make intent explicit. The variable authPassword should just be set to databaseRootPassword unconditionally.

Comment on lines +27 to +29
const updatePasswordSchema = z.object({
password: z.string().min(1, "Password is required"),
});
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.

P2 Consider adding password confirmation field

The form only collects the new password once. A typo in the new password will silently lock the database with an incorrect credential. Adding a "Confirm password" field and validating that both values match (e.g. with a Zod refine check) would prevent this class of user error.

…date failures

- Improved error messages when updating the database password to provide clearer guidance based on the error type.
- Added specific feedback for cases where the database container is not running, prompting users to start the service before attempting to change the password.
…atabase routers

- Added confirmation password field and validation to the `UpdateDatabasePassword` component.
- Refactored password update logic in MariaDB, MongoDB, MySQL, Postgres, and Redis routers to utilize database transactions for improved reliability.
- Ensured consistent handling of password updates across all database types, enhancing user experience and security.
@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Apr 4, 2026
Siumauricio and others added 2 commits April 4, 2026 09:27
…e routers

- Updated password validation in MariaDB, MongoDB, MySQL, Postgres, and Redis routers to enforce a regex pattern that restricts invalid characters.
- Introduced a consistent error message for invalid passwords to improve user guidance and ensure database compatibility.
- Refactored password validation logic in the schema files to utilize shared constants for regex and messages, promoting code reuse and maintainability.
@Siumauricio Siumauricio merged commit b2ca51c into canary Apr 4, 2026
4 checks passed
@Siumauricio Siumauricio deleted the 4041-add-ability-to-change-services-password-like-mysql-and-whatnot branch April 4, 2026 15:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add ability to change services password like mysql and whatnot

1 participant