mirror of
https://github.com/binaricat/Netcatty.git
synced 2026-10-29 18:11:40 +00:00
fix(sftp): resolve trusted local tar before cwd switch
Use the Windows System32 tar.exe for local availability checks and compression so an upload sibling tar.exe cannot hijack execution. Keep Unix tar lookup unchanged and update command assertions. Residual P2: exclude patterns still interpret glob metacharacters in archive paths; glob escaping is intentionally deferred.
This commit is contained in:
1 parent
4abe993250
commit
73ff25a314
2 files changed
+17
-3
No files matched your search
@@ -395,12 +395,21 @@ function init(deps) {
|
||||
transferBridge = deps.transferBridge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve Windows tar before switching to an upload-controlled directory.
|
||||
*/
|
||||
function resolveLocalTarCommand() {
|
||||
return process.platform === 'win32'
|
||||
? path.join(process.env.SystemRoot || process.env.windir || 'C:\\Windows', 'System32', 'tar.exe')
|
||||
: 'tar';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if tar command is available on the system
|
||||
*/
|
||||
async function checkTarAvailable(signal) {
|
||||
return new Promise((resolve) => {
|
||||
const tar = spawn('tar', ['--version'], { stdio: 'ignore' });
|
||||
const tar = spawn(resolveLocalTarCommand(), ['--version'], { stdio: 'ignore' });
|
||||
let settled = false;
|
||||
let childClosed = false;
|
||||
let forceKillTimer = null;
|
||||
@@ -513,7 +522,7 @@ async function compressFolder(folderPath, outputPath, compressionId, sendProgres
|
||||
tarArgs.push(`--exclude=${path.relative(parentDir, outputPath).split(path.sep).join('/')}`);
|
||||
}
|
||||
tarArgs.push(folderName);
|
||||
const tar = spawn('tar', tarArgs, {
|
||||
const tar = spawn(resolveLocalTarCommand(), tarArgs, {
|
||||
cwd: parentDir,
|
||||
stdio: ['ignore', outputFd, 'pipe']
|
||||
});
|
||||
|
||||
@@ -9,6 +9,10 @@ const path = require("node:path");
|
||||
const { EventEmitter } = require("node:events");
|
||||
const test = require("node:test");
|
||||
|
||||
const localTarCommand = process.platform === "win32"
|
||||
? path.join(process.env.SystemRoot || process.env.windir || "C:\\Windows", "System32", "tar.exe")
|
||||
: "tar";
|
||||
|
||||
// The bridge destructures spawn and getTempFilePath at load time, so record
|
||||
// tar calls and redirect temp archives before requiring it.
|
||||
let tempDir = null;
|
||||
@@ -91,7 +95,7 @@ async function compressAndList(folderPath) {
|
||||
folderName: "folder",
|
||||
totalBytes: 7,
|
||||
});
|
||||
const tarCall = spawnCalls.find((call) => call.command === "tar" && call.args.includes("-czf"));
|
||||
const tarCall = spawnCalls.find((call) => call.command === localTarCommand && call.args.includes("-czf"));
|
||||
return { result, archiveEntries, tarCall };
|
||||
}
|
||||
|
||||
@@ -103,6 +107,7 @@ test("local tar gets its paths through cwd and stdout instead of argv", async (t
|
||||
const { result, archiveEntries, tarCall } = await compressAndList(folderPath);
|
||||
|
||||
assert.equal(result.success, true);
|
||||
assert.equal(spawnCalls.find((call) => call.args.includes("--version"))?.command, localTarCommand);
|
||||
assert.ok(tarCall, "local tar compression must be spawned");
|
||||
assert.equal(tarCall.options.cwd, path.dirname(folderPath));
|
||||
assert.equal(tarCall.args.includes("-C"), false, "parent directory must not be passed through argv");
|
||||
|
||||
Reference in new issue
Block a user