mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-07 10:34:44 +00:00
fix(matrix): validate CLI numeric option ranges
Validates Matrix CLI numeric option ranges before invoking setup or verification side effects. `--initial-sync-limit` must now be non-negative, and `--timeout-ms` must now be positive. Original PR by @rohitjavvadi. Verification: - `node scripts/run-vitest.mjs extensions/matrix/src/cli.test.ts --maxWorkers=1` - autoreview clean - Crabbox AWS `cbx_5c32f138ab3a` / `swift-lobster`, run `run_6e133b8b82e7`: `check:changed` passed - exact PR head CI green: `d75f118299029b0516311646276cd2d6582379c5`
This commit is contained in:
@@ -401,6 +401,20 @@ describe("matrix CLI verification commands", () => {
|
||||
expect(runMatrixSelfVerificationMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects non-positive Matrix self-verification timeout values", async () => {
|
||||
const program = buildProgram();
|
||||
|
||||
await program.parseAsync(["matrix", "verify", "self", "--timeout-ms", "-1"], {
|
||||
from: "user",
|
||||
});
|
||||
|
||||
expect(process.exitCode).toBe(1);
|
||||
expect(consoleErrorMock).toHaveBeenCalledWith(
|
||||
"Self-verification failed: --timeout-ms must be a positive integer",
|
||||
);
|
||||
expect(runMatrixSelfVerificationMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("requests Matrix self-verification and prints the follow-up SAS commands", async () => {
|
||||
requestMatrixVerificationMock.mockResolvedValue(
|
||||
mockMatrixVerificationSummary({
|
||||
@@ -1076,6 +1090,34 @@ describe("matrix CLI verification commands", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects negative Matrix initial sync limits at the CLI boundary", async () => {
|
||||
const program = buildProgram();
|
||||
|
||||
await program.parseAsync(
|
||||
[
|
||||
"matrix",
|
||||
"account",
|
||||
"add",
|
||||
"--homeserver",
|
||||
"https://matrix.example.org",
|
||||
"--user-id",
|
||||
"@ops:example.org",
|
||||
"--password",
|
||||
"secret",
|
||||
"--initial-sync-limit",
|
||||
"-1",
|
||||
],
|
||||
{ from: "user" },
|
||||
);
|
||||
|
||||
expect(process.exitCode).toBe(1);
|
||||
expect(consoleErrorMock).toHaveBeenCalledWith(
|
||||
"Account setup failed: --initial-sync-limit must be a non-negative integer",
|
||||
);
|
||||
expect(matrixSetupValidateInputMock).not.toHaveBeenCalled();
|
||||
expect(matrixRuntimeReplaceConfigFileMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("enables E2EE and bootstraps verification from matrix account add", async () => {
|
||||
matrixRuntimeLoadConfigMock.mockReturnValue({ channels: {} });
|
||||
matrixSetupApplyAccountConfigMock.mockImplementation(
|
||||
|
||||
@@ -232,7 +232,11 @@ function configureCliLogMode(verbose: boolean): void {
|
||||
setMatrixSdkConsoleLogging(verbose);
|
||||
}
|
||||
|
||||
function parseOptionalInt(value: string | undefined, fieldName: string): number | undefined {
|
||||
function parseOptionalInt(
|
||||
value: string | undefined,
|
||||
fieldName: string,
|
||||
opts: { min?: number } = {},
|
||||
): number | undefined {
|
||||
const trimmed = value?.trim();
|
||||
if (!trimmed) {
|
||||
return undefined;
|
||||
@@ -244,6 +248,13 @@ function parseOptionalInt(value: string | undefined, fieldName: string): number
|
||||
if (parsed === undefined) {
|
||||
throw new Error(`${fieldName} must be an integer`);
|
||||
}
|
||||
if (opts.min !== undefined && parsed < opts.min) {
|
||||
throw new Error(
|
||||
opts.min === 1
|
||||
? `${fieldName} must be a positive integer`
|
||||
: `${fieldName} must be a non-negative integer`,
|
||||
);
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
||||
@@ -289,6 +300,9 @@ async function addMatrixAccount(params: {
|
||||
useEnv?: boolean;
|
||||
enableEncryption?: boolean;
|
||||
}): Promise<MatrixCliAccountAddResult> {
|
||||
const initialSyncLimit = parseOptionalInt(params.initialSyncLimit, "--initial-sync-limit", {
|
||||
min: 0,
|
||||
});
|
||||
const runtime = getMatrixRuntime();
|
||||
const cfg = runtime.config.current() as CoreConfig;
|
||||
if (!matrixSetupAdapter.applyAccountConfig) {
|
||||
@@ -305,7 +319,7 @@ async function addMatrixAccount(params: {
|
||||
accessToken: params.accessToken,
|
||||
password: params.password,
|
||||
deviceName: params.deviceName,
|
||||
initialSyncLimit: parseOptionalInt(params.initialSyncLimit, "--initial-sync-limit"),
|
||||
initialSyncLimit,
|
||||
useEnv: params.useEnv === true,
|
||||
};
|
||||
const accountId =
|
||||
@@ -1159,15 +1173,18 @@ async function runMatrixCliVerificationSummaryCommand(params: {
|
||||
async function runMatrixCliSelfVerificationCommand(
|
||||
options: MatrixCliSelfVerificationCommandOptions,
|
||||
): Promise<void> {
|
||||
const { accountId, cfg } = resolveMatrixCliAccountContext(options.account);
|
||||
let resolvedAccountId: string | undefined;
|
||||
await runMatrixCliCommand({
|
||||
verbose: options.verbose === true,
|
||||
json: false,
|
||||
run: async () =>
|
||||
await runMatrixSelfVerification({
|
||||
run: async () => {
|
||||
const timeoutMs = parseOptionalInt(options.timeoutMs, "--timeout-ms", { min: 1 });
|
||||
const { accountId, cfg } = resolveMatrixCliAccountContext(options.account);
|
||||
resolvedAccountId = accountId;
|
||||
return await runMatrixSelfVerification({
|
||||
accountId,
|
||||
cfg,
|
||||
timeoutMs: parseOptionalInt(options.timeoutMs, "--timeout-ms"),
|
||||
timeoutMs,
|
||||
onRequested: (summary) => {
|
||||
printAccountLabel(accountId);
|
||||
printMatrixVerificationSummary(summary);
|
||||
@@ -1184,7 +1201,8 @@ async function runMatrixCliSelfVerificationCommand(
|
||||
console.log("Compare this SAS with the other Matrix client.");
|
||||
},
|
||||
confirmSas: async () => await promptMatrixVerificationSasMatch(),
|
||||
}),
|
||||
});
|
||||
},
|
||||
onText: (summary, verbose) => {
|
||||
printMatrixVerificationSummary(summary);
|
||||
console.log(`Device verified by owner: ${summary.deviceOwnerVerified ? "yes" : "no"}`);
|
||||
@@ -1196,6 +1214,7 @@ async function runMatrixCliSelfVerificationCommand(
|
||||
console.log("Self-verification complete.");
|
||||
},
|
||||
onTextError: () => {
|
||||
const accountId = resolvedAccountId ?? options.account;
|
||||
printGuidance([
|
||||
`Run ${formatMatrixCliCommand("verify self", accountId)} again and accept the request in another verified Matrix client for this account.`,
|
||||
`Then run ${formatMatrixCliCommand("verify status --verbose", accountId)} to confirm Cross-signing verified: yes and Signed by owner: yes.`,
|
||||
|
||||
Reference in New Issue
Block a user