Files
stack/packages/control-board/tests/refusal-redaction.test.mjs

45 lines
1.9 KiB
JavaScript

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { dirname, join } from 'node:path';
const secret = 'sk-test-NOT-A-SECRET-1234';
// JSON.parse quotes a prefix near this fault on Node 26; check partial leaks too.
const malformed = secret;
function scratch(t) {
const root = mkdtempSync(join(tmpdir(), 'r3-'));
t.after(() => rmSync(root, { recursive: true, force: true }));
return root;
}
function write(file, text = malformed) {
mkdirSync(dirname(file), { recursive: true });
writeFileSync(file, text, { mode: 0o600 });
return file;
}
function safe(label, ErrorType, properties = {}) {
return error => {
assert.ok(error instanceof ErrorType);
for (const [key, value] of Object.entries(properties)) assert.equal(error[key], value);
assert.ok(error.message.includes(label), error.message);
assert.doesNotMatch(error.message, /sk-test|Unexpected token/);
assert.doesNotMatch(error.stack, /sk-test/);
assert.equal(error.cause, undefined);
return true;
};
}
import { ConfigError, loadConfig, loadSeen } from '../src/scan.mjs';
for (const kind of ['config', 'seen']) test(`${kind} JSON refusal names only the file`, t => {
const root = scratch(t), file = write(join(root, kind === 'config' ? 'config.json' : 'seen.json'));
assert.throws(() => kind === 'config' ? loadConfig(file) : loadSeen(root), safe(file, ConfigError));
});
for (const kind of ['config', 'seen']) test(`${kind} read refusal retains the filesystem code`, t => {
const root = scratch(t), file = join(root, kind === 'config' ? 'config.json' : 'seen.json');
mkdirSync(file);
assert.throws(() => kind === 'config' ? loadConfig(file) : loadSeen(root), error => {
safe(file, ConfigError)(error);
assert.match(error.message, /\(EISDIR\)$/);
assert.doesNotMatch(error.message, /illegal operation/);
return true;
});
});