mirror of
https://github.com/UNITRONIX/BetterDesk.git
synced 2026-10-25 14:00:53 +00:00
abc00b8804
Bind guest WebSocket sessions to a single target peer, enforce grant lifecycle and atomic usage, add the guest issuer scope, and document the password-less security boundary.\n\nRefs #440\n\nThanks: INSOLVE (Honorary); Marco Jakobs (@jacotec); MyNameisStitch (@MyNameisStitch); Redspin (@playerumpknow)
117 lines
4.4 KiB
JavaScript
117 lines
4.4 KiB
JavaScript
'use strict';
|
|
|
|
const assert = require('node:assert/strict');
|
|
const test = require('node:test');
|
|
|
|
const {
|
|
OUT_OF_SCOPE,
|
|
atLeastVersion,
|
|
calculateOverall,
|
|
containsUnexpectedSkip,
|
|
discoverSecurityManifests,
|
|
extractPyprojectDependencies,
|
|
formatCommand,
|
|
parseArgs,
|
|
parseVersion,
|
|
processInvocation,
|
|
redactSensitive,
|
|
resultStatus,
|
|
run,
|
|
} = require('./local-gate');
|
|
|
|
test('argument parsing keeps the gate local and supports dry runs', () => {
|
|
const options = parseArgs(['--dry-run', '--report-dir', '.local-test-results/test']);
|
|
assert.equal(options.dryRun, true);
|
|
assert.match(options.reportDir, /local-test-results[\\/]+test$/u);
|
|
});
|
|
|
|
test('command formatting redacts database credentials', () => {
|
|
const command = formatCommand('node', [
|
|
'scripts/local-docker-smoke.js',
|
|
'--database-url',
|
|
'postgres://user:password@example.test:5432/db?sslmode=disable',
|
|
]);
|
|
assert.match(command, /postgres:\/\/user:\[REDACTED\]@example\.test/u);
|
|
assert.doesNotMatch(command, /password/u);
|
|
});
|
|
|
|
test('captured diagnostics redact passwords and bearer tokens', () => {
|
|
const safe = redactSensitive(
|
|
'password=plain-secret token:plain-token Authorization: Bearer bearer-secret',
|
|
);
|
|
assert.doesNotMatch(safe, /plain-secret|plain-token|bearer-secret/u);
|
|
assert.match(safe, /\[REDACTED\]/u);
|
|
});
|
|
|
|
test('Windows command shims are invoked through cmd.exe', () => {
|
|
const invocation = processInvocation('npm.cmd', ['--version']);
|
|
if (process.platform === 'win32') {
|
|
assert.equal(invocation.command, 'cmd.exe');
|
|
assert.deepEqual(invocation.args.slice(0, 3), ['/d', '/s', '/c']);
|
|
assert.match(invocation.args[3], /npm\.cmd --version/u);
|
|
} else {
|
|
assert.equal(invocation.command, 'npm.cmd');
|
|
}
|
|
});
|
|
|
|
test('skips are blocking unless explicitly allowed', () => {
|
|
assert.equal(containsUnexpectedSkip('--- SKIP: Docker is not available'), true);
|
|
assert.equal(containsUnexpectedSkip('Tests: 12 passed, 0 skipped'), false);
|
|
assert.equal(resultStatus({ code: 0, stdout: 'SKIP: unavailable', stderr: '' }), 'BLOCKED');
|
|
assert.equal(
|
|
resultStatus({ code: 0, stdout: 'SKIP: unavailable', stderr: '' }, { allowSkip: true }),
|
|
'PASS',
|
|
);
|
|
assert.equal(
|
|
resultStatus({ code: 0, stdout: '1 skipped', stderr: '' }, { expectedSkip: true }),
|
|
'OUT_OF_SCOPE',
|
|
);
|
|
assert.equal(resultStatus({ code: null, error: { code: 'ENOENT' } }), 'BLOCKED');
|
|
});
|
|
|
|
test('version checks compare semantic versions conservatively', () => {
|
|
assert.deepEqual(parseVersion('go version go1.26.6 windows/amd64'), {
|
|
major: 1,
|
|
minor: 26,
|
|
patch: 6,
|
|
});
|
|
assert.equal(atLeastVersion(parseVersion('v22.1.0'), { major: 22, minor: 0, patch: 0 }), true);
|
|
assert.equal(atLeastVersion(parseVersion('v21.9.0'), { major: 22, minor: 0, patch: 0 }), false);
|
|
});
|
|
|
|
test('security manifest discovery includes all dependency ecosystems', () => {
|
|
const manifests = discoverSecurityManifests();
|
|
assert.ok(manifests.pythonRequirements.some((file) => file.endsWith('bridges\\modbus\\requirements.txt')
|
|
|| file.endsWith('bridges/modbus/requirements.txt')));
|
|
assert.ok(manifests.pythonProjects.some((file) => file.endsWith('sdks\\python\\pyproject.toml')
|
|
|| file.endsWith('sdks/python/pyproject.toml')));
|
|
assert.deepEqual(manifests.rustProjects, []);
|
|
});
|
|
|
|
test('Python project dependencies can be converted for pip-audit', () => {
|
|
const dependencies = extractPyprojectDependencies('sdks/python/pyproject.toml');
|
|
assert.deepEqual(dependencies, ['websockets>=12.0']);
|
|
});
|
|
|
|
test('overall status blocks on required failures but ignores explicit boundaries', () => {
|
|
const report = {
|
|
results: [
|
|
{ status: 'PASS', required: true },
|
|
{ status: 'OUT_OF_SCOPE', required: false },
|
|
],
|
|
};
|
|
assert.equal(calculateOverall(report), 'PASS');
|
|
report.results.push({ status: 'BLOCKED', required: true });
|
|
assert.equal(calculateOverall(report), 'BLOCKED');
|
|
report.results.push({ status: 'FAIL', required: true });
|
|
assert.equal(calculateOverall(report), 'FAIL');
|
|
assert.equal(OUT_OF_SCOPE.length >= 1, true);
|
|
});
|
|
|
|
test('dry run does not execute the external test suites', async () => {
|
|
const report = await run({ dryRun: true });
|
|
assert.equal(report.dryRun, true);
|
|
assert.equal(report.overall, 'PASS');
|
|
assert.equal(report.results.length, 0);
|
|
});
|