mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-07-22 06:15:24 +02:00
fix(security): redact SSH private key from server read responses
findServerById eagerly loads the sshKey relation (needed for server-side SSH operations) including the plaintext privateKey. server.one and server.remove returned that record to the client, exposing the private key to any member with server:read regardless of canAccessToSSHKeys. Adds redactServerSshKey() in the server service and applies it to the server.one and server.remove responses. No client feature consumes the private key (the SSH key management UI uses the dedicated sshKey router), and server-side callers keep using findServerById directly, so behaviour is unchanged. Closes GHSA-w9cp-jqfw-4xj9
This commit is contained in:
@@ -53,6 +53,27 @@ export const findServerById = async (serverId: string) => {
|
||||
return currentServer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the SSH private key material from a server record before it is sent
|
||||
* to a client. `findServerById` eagerly loads the `sshKey` relation (needed for
|
||||
* server-side SSH operations), but the private key must never leave the server:
|
||||
* no client feature consumes it, and returning it exposed it to any member with
|
||||
* only `server:read`. Server-side callers keep using `findServerById` directly.
|
||||
*/
|
||||
export const redactServerSshKey = <
|
||||
T extends { sshKey?: { privateKey: string } | null },
|
||||
>(
|
||||
serverRecord: T,
|
||||
): T => {
|
||||
if (!serverRecord.sshKey) {
|
||||
return serverRecord;
|
||||
}
|
||||
return {
|
||||
...serverRecord,
|
||||
sshKey: { ...serverRecord.sshKey, privateKey: "" },
|
||||
};
|
||||
};
|
||||
|
||||
export const findServersByUserId = async (userId: string) => {
|
||||
const orgs = await db.query.organization.findMany({
|
||||
where: eq(organization.ownerId, userId),
|
||||
|
||||
Reference in New Issue
Block a user