Skip to content
Draft
Changes from all 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
4 changes: 2 additions & 2 deletions backend/routes/ssh.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,130 +210,130 @@
});

// Debug SSH connectivity
router.post('/debug', async (req, res) => {
const { host, username, password, port = 22 } = req.body;

if (!host || !username || !password) {
return res.status(400).json({
success: false,
error: 'Missing required connection parameters'
});
}

const debug = {
timestamp: new Date().toISOString(),
host,
port,
username,
tests: {}
};

try {
// Test 1: Basic network connectivity
try {
const { execSync } = require('child_process');
const pingResult = execSync(`ping -c 1 -W 3 ${host}`, { timeout: 5000 }).toString();
const { execFileSync } = require('child_process');
const pingResult = execFileSync('ping', ['-c', '1', '-W', '3', host], { timeout: 5000 }).toString();
debug.tests.ping = { success: true, output: pingResult.trim() };
} catch (error) {
debug.tests.ping = { success: false, error: error.message };
}

// Test 2: Port connectivity
try {
const net = require('net');
const socket = new net.Socket();

await new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
socket.destroy();
reject(new Error('Connection timeout'));
}, 5000);

socket.connect(port, host, () => {
clearTimeout(timeout);
socket.destroy();
resolve();
});

socket.on('error', (err) => {
clearTimeout(timeout);
reject(err);
});
});

debug.tests.portConnectivity = { success: true };
} catch (error) {
debug.tests.portConnectivity = { success: false, error: error.message };
}

// Test 3: SSH connection with password
const ssh = new NodeSSH();
try {
await ssh.connect({
host,
username,
password,
port,
readyTimeout: 10000,
algorithms: {
serverHostKey: ['ssh-rsa', 'ssh-dss', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp521', 'ssh-ed25519'],
hmac: ['hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1'],
cipher: ['aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-gcm', 'aes256-gcm'],
compress: ['none']
}
});

debug.tests.sshConnection = { success: true };

// Test basic commands
const whoamiResult = await ssh.execCommand('whoami');
debug.tests.whoami = {
success: whoamiResult.code === 0,
output: whoamiResult.stdout || whoamiResult.stderr
};

const homeResult = await ssh.execCommand('pwd && ls -la');
debug.tests.homeDirectory = {
success: homeResult.code === 0,
output: homeResult.stdout || homeResult.stderr
};

const sshDirResult = await ssh.execCommand('ls -la ~/.ssh || echo "NO_SSH_DIR"');
debug.tests.sshDirectory = {
success: true,
output: sshDirResult.stdout || sshDirResult.stderr
};

await ssh.dispose();

} catch (error) {
debug.tests.sshConnection = { success: false, error: error.message };
}

// Test 4: Check if SSH keys exist locally
const sshDir = '/root/.ssh';
const privateKeyPath = path.join(sshDir, 'id_rsa');
const publicKeyPath = path.join(sshDir, 'id_rsa.pub');

debug.tests.localSshKeys = {
sshDirExists: await fs.pathExists(sshDir),
privateKeyExists: await fs.pathExists(privateKeyPath),
publicKeyExists: await fs.pathExists(publicKeyPath)
};

if (await fs.pathExists(publicKeyPath)) {
const publicKey = await fs.readFile(publicKeyPath, 'utf8');
debug.tests.localSshKeys.publicKeyLength = publicKey.length;
debug.tests.localSshKeys.publicKeyPreview = publicKey.substring(0, 50) + '...';
}

res.json({ success: true, debug });

} catch (error) {
debug.tests.generalError = { success: false, error: error.message };
res.json({ success: false, debug });
}
});

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a system command
, but is not rate-limited.
This route handler performs
a file system access
, but is not rate-limited.
This route handler performs
a file system access
, but is not rate-limited.
This route handler performs
a file system access
, but is not rate-limited.
This route handler performs
a file system access
, but is not rate-limited.
This route handler performs
a file system access
, but is not rate-limited.

// Test SSH key authentication
router.post('/test-key', async (req, res) => {
Expand Down
Loading