fix: harden rclone environment and credential redaction

This commit is contained in:
github-actions[bot] 2026-09-04 23:07:52 +00:00 committed by Furox88
parent 5ab6b0701d
commit 27140c93d2
4 changed files with 38 additions and 1 deletions

View File

@ -2,6 +2,7 @@ import {
getSafeRcloneErrorMessage,
redactRcloneCredentials,
} from "@dokploy/server/utils/backups/redact";
import { quote } from "shell-quote";
import { describe, expect, it } from "vitest";
describe("redactRcloneCredentials (#4621)", () => {
@ -84,4 +85,15 @@ describe("redactRcloneCredentials (#4621)", () => {
}
expect(safe.match(/\[REDACTED\]/g)?.length).toBe(5);
});
it("should fully redact shell-quote output with embedded quotes and whitespace", () => {
const secret = "PART_A' PART_B\" $PART_C;\\PART_D";
const cmd = `rclone lsf --s3-secret-access-key=${quote([secret])} --s3-region=us-east-1 :s3:bucket`;
const redacted = redactRcloneCredentials(cmd);
for (const fragment of ["PART_A", "PART_B", "PART_C", "PART_D"]) {
expect(redacted).not.toContain(fragment);
}
expect(redacted).toContain('--s3-secret-access-key="[REDACTED]"');
expect(redacted).toContain("--s3-region=us-east-1");
});
});

View File

@ -407,4 +407,21 @@ describe("FTP TLS certificate verification", () => {
}).success,
).toBe(true);
});
test("forces certificate verification on after user flags", async () => {
const result = await getRclonePathAndFlags(
destination({
provider: RCLONE_DESTINATION_PROVIDERS.FTP,
endpoint: "storage.example.com",
accessKey: "backup-user",
secretAccessKey: "",
region: "",
bucket: "backups",
additionalFlags: ["--ftp-explicit-tls"],
}),
);
expect(result.flags.slice(-2)).toEqual([
"--ftp-no-check-certificate=false",
"--no-check-certificate=false",
]);
});
});

View File

@ -5,7 +5,7 @@
*/
export const redactRcloneCredentials = (command: string): string => {
return command.replace(
/(--(?:s3-access-key-id|s3-secret-access-key|ftp-pass|sftp-pass|sftp-key-file-pass)=)(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|[^\s]+)/g,
/(--(?:s3-access-key-id|s3-secret-access-key|ftp-pass|sftp-pass|sftp-key-file-pass)=)(?:(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\\[^\r\n]|[^\s"'\\])+)/g,
'$1"[REDACTED]"',
);
};

View File

@ -197,6 +197,14 @@ export const getRclonePathAndFlags = async (
flags.push(`--${backend}-pass=${quote([obscuredPassword])}`);
}
flags.push(...additionalFlags);
if (provider === RCLONE_DESTINATION_PROVIDERS.FTP) {
// CLI options override RCLONE_* environment defaults. Keep TLS
// certificate verification enabled on the execution host.
flags.push(
"--ftp-no-check-certificate=false",
"--no-check-certificate=false",
);
}
return {
flags,
path: `:${backend}:${joinRclonePath(destination.bucket, path)}`,