mirror of https://github.com/openclaw/openclaw.git
test: cover device pairing token hardening
This commit is contained in:
parent
37c4db02ab
commit
2e5f365e43
|
|
@ -192,6 +192,7 @@ Docs: https://docs.openclaw.ai
|
|||
- Clawdock: avoid Zsh readonly variable collisions in helper scripts. (#15501) Thanks @nkelner.
|
||||
- Memory: switch default local embedding model to the QAT `embeddinggemma-300m-qat-Q8_0` variant for better quality at the same footprint. (#15429) Thanks @azade-c.
|
||||
- Docs/Mermaid: remove hardcoded Mermaid init theme blocks from four docs diagrams so dark mode inherits readable theme defaults. (#15157) Thanks @heytulsiprasad.
|
||||
- Security/Device pairing: generate 256-bit base64url device tokens and use byte-safe constant-time verification to avoid token-compare edge-case failures.
|
||||
|
||||
## 2026.2.12
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,25 @@ import {
|
|||
} from "./device-pairing.js";
|
||||
|
||||
describe("device pairing tokens", () => {
|
||||
test("generates base64url device tokens with 256-bit entropy output length", async () => {
|
||||
const baseDir = await mkdtemp(join(tmpdir(), "openclaw-device-pairing-"));
|
||||
const request = await requestDevicePairing(
|
||||
{
|
||||
deviceId: "device-1",
|
||||
publicKey: "public-key-1",
|
||||
role: "operator",
|
||||
scopes: ["operator.admin"],
|
||||
},
|
||||
baseDir,
|
||||
);
|
||||
await approveDevicePairing(request.request.requestId, baseDir);
|
||||
|
||||
const paired = await getPairedDevice("device-1", baseDir);
|
||||
const token = paired?.tokens?.operator?.token;
|
||||
expect(token).toBeTruthy();
|
||||
expect(token).toMatch(/^[A-Za-z0-9_-]{43}$/);
|
||||
});
|
||||
|
||||
test("preserves existing token scopes when rotating without scopes", async () => {
|
||||
const baseDir = await mkdtemp(join(tmpdir(), "openclaw-device-pairing-"));
|
||||
const request = await requestDevicePairing(
|
||||
|
|
@ -78,4 +97,31 @@ describe("device pairing tokens", () => {
|
|||
expect(mismatch.ok).toBe(false);
|
||||
expect(mismatch.reason).toBe("token-mismatch");
|
||||
});
|
||||
|
||||
test("treats multibyte same-length token input as mismatch without throwing", async () => {
|
||||
const baseDir = await mkdtemp(join(tmpdir(), "openclaw-device-pairing-"));
|
||||
const request = await requestDevicePairing(
|
||||
{
|
||||
deviceId: "device-1",
|
||||
publicKey: "public-key-1",
|
||||
role: "operator",
|
||||
scopes: ["operator.read"],
|
||||
},
|
||||
baseDir,
|
||||
);
|
||||
await approveDevicePairing(request.request.requestId, baseDir);
|
||||
const paired = await getPairedDevice("device-1", baseDir);
|
||||
const token = paired?.tokens?.operator?.token ?? "";
|
||||
|
||||
const mismatch = await verifyDeviceToken({
|
||||
deviceId: "device-1",
|
||||
token: "é".repeat(token.length),
|
||||
role: "operator",
|
||||
scopes: ["operator.read"],
|
||||
baseDir,
|
||||
});
|
||||
|
||||
expect(mismatch.ok).toBe(false);
|
||||
expect(mismatch.reason).toBe("token-mismatch");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue