From 3d42a2c09c8f380d8abecba5e47fccd0ab7b6910 Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Wed, 15 Jul 2026 14:31:44 +0800 Subject: [PATCH] Merge commit from fork --- src/backend/ssh/tunnel.ts | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/backend/ssh/tunnel.ts b/src/backend/ssh/tunnel.ts index f5e08e1e..232397f0 100644 --- a/src/backend/ssh/tunnel.ts +++ b/src/backend/ssh/tunnel.ts @@ -2056,22 +2056,47 @@ app.post( ); } } else { + if (!endpointHost.id) { + throw new Error("Endpoint host not found"); + } + + const endpointAccess = await permissionManager.canAccessHost( + userId, + endpointHost.id, + "read", + ); + if (!endpointAccess.hasAccess) { + tunnelLogger.warn( + "User attempted tunnel connect without endpoint access", + { + operation: "tunnel_connect_endpoint_unauthorized", + userId, + hostId: endpointHost.id, + tunnelName, + }, + ); + throw new Error("Endpoint host not found"); + } + tunnelConfig.endpointIP = endpointHost.ip; tunnelConfig.endpointSSHPort = endpointHost.port; tunnelConfig.endpointUsername = endpointHost.username; tunnelConfig.endpointAuthMethod = endpointHost.authType; tunnelConfig.endpointKeyType = endpointHost.keyType; - tunnelConfig.endpointCredentialId = endpointHost.credentialId; - tunnelConfig.endpointUserId = endpointHost.userId; + tunnelConfig.endpointCredentialId = + endpointHost.userId === userId + ? endpointHost.credentialId + : undefined; + tunnelConfig.endpointUserId = userId; // Resolve credentials server-side instead of from HTTP response - if (endpointHost.id && endpointHost.userId) { + if (endpointHost.id) { try { const { resolveHostById } = await import("./host-resolver.js"); const resolved = await resolveHostById( endpointHost.id, - endpointHost.userId, + userId, ); if (resolved) { tunnelConfig.endpointPassword = resolved.password;