Files
2026-07-13 13:39:12 +08:00

269 lines
11 KiB
TypeScript

/**
* TDD security tests: CCR cross-tenant IDOR + bounded memory + scoped feedback.
* Run: node --import tsx/esm --test tests/unit/compression/ccr-cross-tenant.test.ts
*
* RED → GREEN: these tests define the security contract and must drive the fix.
*
* Security assertions:
* 1. Cross-tenant IDOR blocked: principal B cannot retrieve a block stored by A.
* 2. Anonymous principal cannot retrieve a block stored by a named principal.
* 3. Memory bound: store never exceeds MAX_CCR_ENTRIES (FIFO eviction).
* 4. Scoped feedback: A's retrievals do NOT flip B's shouldSkipCompression.
* 5. handleCcrRetrieve end-to-end: cross-tenant retrieve returns not-found error.
*/
import crypto from "node:crypto";
import { describe, it, beforeEach } from "node:test";
import assert from "node:assert/strict";
import {
storeBlock,
retrieveBlock,
recordRetrieval,
shouldSkipCompression,
resetCcrStore,
handleCcrRetrieve,
ccrEngine,
MAX_CCR_ENTRIES,
} from "../../../open-sse/services/compression/engines/ccr/index.ts";
// ─── helpers ──────────────────────────────────────────────────────────────────
function makeText(seed: string, length: number = 700): string {
return seed.repeat(Math.ceil(length / seed.length)).slice(0, length);
}
const TEXT_A = makeText("content for principal A — confidential data");
const TEXT_B = makeText("content for principal B — different tenant");
function contentHash(text: string): string {
return crypto.createHash("sha256").update(text).digest("hex").slice(0, 24);
}
// ─── cross-tenant IDOR isolation ─────────────────────────────────────────────
describe("ccr security: cross-tenant IDOR isolation", () => {
beforeEach(() => resetCcrStore());
it("[HIGH] principal B cannot retrieve a block stored by principal A", () => {
const hash = storeBlock(TEXT_A, "principalA");
// Same principal can retrieve
const resultA = retrieveBlock(hash, "principalA");
assert.equal(resultA, TEXT_A, "principal A must be able to retrieve its own block");
// Different principal is blocked — THE CORE SECURITY ASSERTION
const resultB = retrieveBlock(hash, "principalB");
assert.equal(
resultB,
null,
"[HIGH IDOR] principal B must NOT be able to retrieve principal A's block"
);
});
it("[HIGH] anonymous principal cannot retrieve a block stored by a named principal", () => {
const hash = storeBlock(TEXT_A, "principalA");
const resultAnon = retrieveBlock(hash, undefined);
assert.equal(
resultAnon,
null,
"[HIGH IDOR] anonymous principal must NOT retrieve a named principal's block"
);
});
it("named principal cannot retrieve a block stored by anonymous", () => {
const hash = storeBlock(TEXT_B, undefined);
const resultA = retrieveBlock(hash, "principalA");
assert.equal(resultA, null, "principal A must NOT retrieve an anonymous block");
// The anonymous store owner can retrieve
const resultAnon = retrieveBlock(hash, undefined);
assert.equal(resultAnon, TEXT_B, "anonymous can retrieve its own block");
});
it("principal with no stored block cannot retrieve via another principal's hash", () => {
// Store TEXT_A only under principalA — principalB never stores anything.
const hashA = storeBlock(TEXT_A, "principalA");
// principalA can retrieve their own block
assert.equal(retrieveBlock(hashA, "principalA"), TEXT_A, "A can retrieve its own block");
// principalB never stored anything — cannot retrieve even with the correct hash
assert.equal(
retrieveBlock(hashA, "principalB"),
null,
"[HIGH IDOR] B (never stored) cannot retrieve A's block by reusing A's hash"
);
// anonymous similarly cannot
assert.equal(
retrieveBlock(hashA, undefined),
null,
"[HIGH IDOR] anonymous cannot retrieve A's block"
);
});
});
// ─── handleCcrRetrieve end-to-end isolation ───────────────────────────────────
describe("ccr security: handleCcrRetrieve end-to-end isolation", () => {
beforeEach(() => resetCcrStore());
it("handleCcrRetrieve with correct callerId returns content", () => {
const hash = storeBlock(TEXT_A, "callerA");
const result = handleCcrRetrieve({ hash }, "callerA");
assert.ok("content" in result, "same-caller retrieve must return content");
assert.equal((result as { content: string }).content, TEXT_A);
});
it("[HIGH] handleCcrRetrieve with wrong callerId returns not-found error", () => {
const hash = storeBlock(TEXT_A, "callerA");
const result = handleCcrRetrieve({ hash }, "callerB");
assert.ok(
"error" in result,
"[HIGH IDOR] cross-tenant retrieve via handleCcrRetrieve must return error, not content"
);
assert.ok(!("content" in result), "[HIGH IDOR] cross-tenant retrieve must NOT return content");
});
it("handleCcrRetrieve without callerId cannot access named-principal block", () => {
const hash = storeBlock(TEXT_A, "callerA");
const result = handleCcrRetrieve({ hash }, undefined);
assert.ok("error" in result, "anonymous retrieve of named-principal block must return error");
});
it("handleCcrRetrieve returns error for completely unknown hash", () => {
const result = handleCcrRetrieve({ hash: "000000000000000000000000" }, "anyPrincipal");
assert.ok("error" in result, "unknown hash must return error");
assert.ok(typeof (result as { error: string }).error === "string");
});
it("handleCcrRetrieve returns error for missing hash parameter", () => {
// @ts-expect-error — intentional wrong call to verify guard
const result = handleCcrRetrieve({}, "caller");
assert.ok("error" in result, "missing hash must return error");
});
});
// ─── scoped retrieval feedback ────────────────────────────────────────────────
describe("ccr security: [MEDIUM] scoped retrieval feedback (shouldSkipCompression)", () => {
beforeEach(() => resetCcrStore());
it("A's retrievals do NOT flip B's shouldSkipCompression", () => {
const hash = storeBlock(TEXT_A, "principalA");
storeBlock(TEXT_A, "principalB"); // same content stored under B
// Record retrievals for A above the threshold (default 3)
recordRetrieval(hash, "principalA");
recordRetrieval(hash, "principalA");
recordRetrieval(hash, "principalA");
// A's compression should be skipped
assert.equal(
shouldSkipCompression(hash, "principalA"),
true,
"A's compression should be skipped after threshold retrievals"
);
// B's compression must NOT be affected
assert.equal(
shouldSkipCompression(hash, "principalB"),
false,
"[MEDIUM] A's retrievals must NOT flip B's shouldSkipCompression"
);
});
it("shouldSkipCompression returns false for a principal with no retrievals", () => {
const hash = storeBlock(TEXT_A, "principalA");
assert.equal(shouldSkipCompression(hash, "principalA"), false);
assert.equal(shouldSkipCompression(hash, "principalB"), false);
assert.equal(shouldSkipCompression(hash, undefined), false);
});
});
// ─── bounded memory (FIFO eviction) ──────────────────────────────────────────
describe("ccr security: [MEDIUM] bounded memory (FIFO eviction)", () => {
beforeEach(() => resetCcrStore());
it("MAX_CCR_ENTRIES is exported and positive", () => {
assert.ok(typeof MAX_CCR_ENTRIES === "number", "MAX_CCR_ENTRIES must be a number");
assert.ok(MAX_CCR_ENTRIES > 0, "MAX_CCR_ENTRIES must be positive");
});
it("FIFO eviction: oldest entry is evicted when cap is reached", () => {
const principal = "evictionTest";
// Fill to exactly cap with unique blocks
const firstText = `eviction block 0 ${"y".repeat(30)}`;
const firstHash = storeBlock(firstText, principal);
for (let i = 1; i < MAX_CCR_ENTRIES; i++) {
storeBlock(`eviction block ${i} ${"y".repeat(30)}`, principal);
}
// Confirm first block is present before overflow
assert.equal(
retrieveBlock(firstHash, principal),
firstText,
"first block must be present at exactly-cap state"
);
// Insert one more unique block — should evict the first (oldest) entry
storeBlock(`eviction overflow block ${"z".repeat(50)}`, principal);
// First block should now be gone
assert.equal(
retrieveBlock(firstHash, principal),
null,
"[MEDIUM] FIFO eviction: oldest block must be evicted when cap is reached"
);
});
it("store does not grow unboundedly beyond MAX_CCR_ENTRIES distinct principals", () => {
// Insert MAX+5 distinct (principal, content) pairs and verify the overall store
// did not go unbounded by checking that the first inserted block is evicted.
const firstText = `overflow test block 0 ${"a".repeat(40)}`;
const firstPrincipal = "overflow-p-0";
const firstHash = storeBlock(firstText, firstPrincipal);
for (let i = 1; i < MAX_CCR_ENTRIES + 5; i++) {
storeBlock(`overflow test block ${i} ${"a".repeat(40)}`, `overflow-p-${i}`);
}
// The first inserted store-key should have been evicted by FIFO
assert.equal(
retrieveBlock(firstHash, firstPrincipal),
null,
"[MEDIUM] unbounded-growth prevented: first inserted entry must be evicted after MAX+5 inserts"
);
});
});
// ─── engine-level scoping: apply() threads principalId end-to-end ─────────────
describe("ccr security: [HIGH] ccrEngine.apply scopes the stored block to the principal", () => {
beforeEach(() => resetCcrStore());
const bigBlock = makeText("a large block that CCR would normally compress ", 5000);
const makeBody = () => ({ messages: [{ role: "user", content: bigBlock }] });
it("apply with a principalId stores the block retrievable ONLY by that principal", () => {
const result = ccrEngine.apply(makeBody(), {
principalId: "principalA",
stepConfig: { minChars: 100 },
});
assert.equal(result.compressed, true, "CCR compresses the large block");
const hash = contentHash(bigBlock);
assert.equal(retrieveBlock(hash, "principalA"), bigBlock, "owner principal A can retrieve");
assert.equal(
retrieveBlock(hash, "principalB"),
null,
"[HIGH IDOR] principal B must NOT retrieve principal A's apply()-stored block"
);
});
});