Include canonical hashing in restricted package execution
This commit is contained in:
@@ -37,7 +37,7 @@ let
|
||||
mkdir -p "$out"
|
||||
cat > entry.mjs <<'JS'
|
||||
export {definePortableRegistry,QxReject} from '${core}/dist/portable.js';
|
||||
export {encodeArgument,decodeArgument,canonicalJson,parseJson} from '${core}/dist/value.js';
|
||||
export {encodeArgument,decodeArgument,canonicalJson,parseJson,hashJson} from '${core}/dist/value.js';
|
||||
export {workspaceId,operationId,objectId,entryId,hashIdentity} from '${core}/dist/identity.js';
|
||||
export {reference} from '${core}/dist/references.js';
|
||||
export {CodecError,ExecutionError} from '${core}/dist/limits.js';
|
||||
|
||||
@@ -307,6 +307,47 @@ test("the checked portable SDK keeps codecs and nested graph ports inside the fr
|
||||
await f.close();
|
||||
}
|
||||
});
|
||||
test("checked handlers hash canonical values without ambient capabilities", async () => {
|
||||
const sdk = process.env.QUIXOS_TEST_SDK;
|
||||
const C = await import(sdk);
|
||||
const workspace = C.workspaceId("workspace:restricted");
|
||||
const text = { kind: "scalar", name: "string" };
|
||||
const value = {
|
||||
kind: "record",
|
||||
fields: {
|
||||
text,
|
||||
options: {
|
||||
kind: "record",
|
||||
fields: {
|
||||
level: { kind: "scalar", name: "int32" },
|
||||
enabled: { kind: "scalar", name: "bool" },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const declarations = [
|
||||
{ id: "test", name: "test", effect: "snapshot", receiver: null, input: value, output: text, methods: [] },
|
||||
];
|
||||
const source = `import {definePortableRegistry,hashJson} from 'qx:core'; export const registry=definePortableRegistry(${JSON.stringify(declarations)},{test:ctx=>hashJson('test-content',ctx.input)});`;
|
||||
const f = await fixture(source, { sdk: [{ name: "qx:core", path: sdk }] });
|
||||
try {
|
||||
const input = { text: "雨后的书店", options: { level: 3, enabled: true } };
|
||||
let expected;
|
||||
for (const candidate of [input, { options: input.options, text: input.text }, { ...input, text: "別の文" }]) {
|
||||
f.start(C.encodeArgument(value, candidate, { workspace }));
|
||||
const result = await f.receive();
|
||||
assert.equal(result.status, "returned");
|
||||
const actual = C.decodeArgument(text, result.output, { workspace });
|
||||
assert.equal(actual, await C.hashJson("test-content", candidate));
|
||||
if (candidate.text === input.text) {
|
||||
expected ??= actual;
|
||||
assert.equal(actual, expected, "Object key order must not invalidate content caches");
|
||||
} else assert.notEqual(actual, expected, "Content changes must invalidate the key");
|
||||
}
|
||||
} finally {
|
||||
await f.close();
|
||||
}
|
||||
});
|
||||
test("ambient clock, entropy, network and native imports are denied", async () => {
|
||||
for (const code of [
|
||||
"Date.now()",
|
||||
|
||||
Reference in New Issue
Block a user