mirror of
https://github.com/nimbold/Firelink.git
synced 2026-07-26 12:08:27 +00:00
fix(release): harden package and engine verifier cleanup
This commit is contained in:
@@ -317,6 +317,54 @@ function runEngine(label, engine, args, timeout = 30000) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function waitForProcessExit(proc, timeoutMs) {
|
||||||
|
if (proc.exitCode !== null || proc.signalCode !== null) {
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise(resolve => {
|
||||||
|
let settled = false;
|
||||||
|
let timer;
|
||||||
|
const finish = value => {
|
||||||
|
if (settled) return;
|
||||||
|
settled = true;
|
||||||
|
clearTimeout(timer);
|
||||||
|
proc.removeListener('exit', onExit);
|
||||||
|
resolve(value);
|
||||||
|
};
|
||||||
|
const onExit = () => finish(true);
|
||||||
|
|
||||||
|
timer = setTimeout(() => finish(false), timeoutMs);
|
||||||
|
proc.once('exit', onExit);
|
||||||
|
if (proc.exitCode !== null || proc.signalCode !== null) {
|
||||||
|
finish(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function terminateProcess(proc, label) {
|
||||||
|
if (proc.exitCode === null && proc.signalCode === null) {
|
||||||
|
try {
|
||||||
|
proc.kill('SIGTERM');
|
||||||
|
} catch {}
|
||||||
|
if (await waitForProcessExit(proc, 2000)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
proc.kill('SIGKILL');
|
||||||
|
} catch {}
|
||||||
|
if (await waitForProcessExit(proc, 2000)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fail(`${label} did not terminate after SIGTERM and SIGKILL.`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const coldStartTimeout = isMacOS ? 120000 : 30000;
|
const coldStartTimeout = isMacOS ? 120000 : 30000;
|
||||||
if (canExecuteTarget) {
|
if (canExecuteTarget) {
|
||||||
runEngine('yt-dlp cold start', 'yt-dlp', ['--version'], coldStartTimeout);
|
runEngine('yt-dlp cold start', 'yt-dlp', ['--version'], coldStartTimeout);
|
||||||
@@ -397,13 +445,9 @@ if (canExecuteTarget) {
|
|||||||
tryFetch();
|
tryFetch();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Clean up
|
// Clean up and wait before the verifier exits so a stuck daemon cannot be
|
||||||
proc.kill('SIGTERM');
|
// left behind on a runner and contaminate later package or smoke checks.
|
||||||
setTimeout(() => {
|
await terminateProcess(proc, 'aria2 RPC verifier process');
|
||||||
try {
|
|
||||||
proc.kill('SIGKILL');
|
|
||||||
} catch {}
|
|
||||||
}, 2000);
|
|
||||||
|
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -96,6 +96,15 @@ export function parseDebianPackagePath(line) {
|
|||||||
return match[1].replace(/^\.\//, '');
|
return match[1].replace(/^\.\//, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isSafePackagePath(packagePath) {
|
||||||
|
if (packagePath === '') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parts = packagePath.split('/');
|
||||||
|
return !parts.includes('..') && (parts[0] === 'usr' || packagePath === 'usr');
|
||||||
|
}
|
||||||
|
|
||||||
function assertSafePackageListing(listing, packageType) {
|
function assertSafePackageListing(listing, packageType) {
|
||||||
const lines = listing.split('\n').filter(Boolean);
|
const lines = listing.split('\n').filter(Boolean);
|
||||||
const paths = packageType === 'deb'
|
const paths = packageType === 'deb'
|
||||||
@@ -109,8 +118,7 @@ function assertSafePackageListing(listing, packageType) {
|
|||||||
: lines.map(line => line.replace(/^\/+/, ''));
|
: lines.map(line => line.replace(/^\/+/, ''));
|
||||||
|
|
||||||
for (const packagePath of paths) {
|
for (const packagePath of paths) {
|
||||||
const parts = packagePath.split('/');
|
if (!isSafePackagePath(packagePath)) {
|
||||||
if (parts.includes('..') || (parts[0] !== 'usr' && packagePath !== 'usr')) {
|
|
||||||
fail(`${packageType} package contains an unsafe path: ${packagePath}`);
|
fail(`${packageType} package contains an unsafe path: ${packagePath}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import test from 'node:test';
|
import test from 'node:test';
|
||||||
|
|
||||||
import { parseDebianPackagePath } from './verify-linux-packages.js';
|
import { isSafePackagePath, parseDebianPackagePath } from './verify-linux-packages.js';
|
||||||
|
|
||||||
test('parses current dpkg-deb listings without a ./ prefix', () => {
|
test('parses current dpkg-deb listings without a ./ prefix', () => {
|
||||||
assert.equal(
|
assert.equal(
|
||||||
@@ -17,6 +17,19 @@ test('parses legacy dpkg-deb listings with a ./ prefix', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('accepts the package root in legacy dpkg-deb listings', () => {
|
||||||
|
assert.equal(
|
||||||
|
parseDebianPackagePath('drwxr-xr-x root/root 0 2026-07-12 07:24 ./'),
|
||||||
|
''
|
||||||
|
);
|
||||||
|
assert.equal(isSafePackagePath(''), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('rejects paths outside the package usr tree', () => {
|
||||||
|
assert.equal(isSafePackagePath('../tmp/firelink'), false);
|
||||||
|
assert.equal(isSafePackagePath('etc/firelink'), false);
|
||||||
|
});
|
||||||
|
|
||||||
test('rejects malformed dpkg-deb listing lines', () => {
|
test('rejects malformed dpkg-deb listing lines', () => {
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => parseDebianPackagePath('not a dpkg-deb listing'),
|
() => parseDebianPackagePath('not a dpkg-deb listing'),
|
||||||
|
|||||||
Reference in New Issue
Block a user