mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-20 01:56:37 +03:00
fix: authenticate the live-server liveness probe
greptile-apps[bot] escalated the identity ladder to a pid AND port both coincidentally reused by different processes. The definitive terminator was available all along: the helper serves an authenticated endpoint and server.json records the token, so the probe now requires a 200 from /status?token=... over HTTP. Nothing but our helper can answer that, which closes the entire misidentification class rather than the next rung. The regression test hosts its responder in a child process (the probe is execFileSync, so a same-process responder can never accept while the parent's event loop is blocked; production helpers are always separate processes). This work was produced with AI assistance (Claude Code). Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Code
parent
9a3f5aa34b
commit
16a84bc390
@@ -300,35 +300,37 @@ function readPointerEntries(repoRoot) {
|
||||
function hasLiveServer(appRoot) {
|
||||
let pid;
|
||||
let port;
|
||||
let token;
|
||||
try {
|
||||
const info = JSON.parse(fs.readFileSync(path.join(appRoot, '.impeccable', 'live', 'server.json'), 'utf-8'));
|
||||
if (!info || typeof info.pid !== 'number') return false;
|
||||
pid = info.pid;
|
||||
port = Number(info.port);
|
||||
token = typeof info.token === 'string' ? info.token : null;
|
||||
process.kill(pid, 0);
|
||||
} catch (err) {
|
||||
// EPERM: the process exists but is not signalable by this user.
|
||||
if (err?.code !== 'EPERM') return false;
|
||||
}
|
||||
// Liveness alone misclassifies a REUSED pid (helper died without removing
|
||||
// server.json, the OS handed the pid to something else, even another node
|
||||
// process). The decisive signal is the recorded PORT: a real helper is
|
||||
// listening on it, a pid squatter is not. The probe is a spawned node
|
||||
// one-liner so it works identically on every platform (no bash, no ps).
|
||||
if (Number.isInteger(port) && port > 0) {
|
||||
// Liveness alone misclassifies a REUSED pid, and a bare TCP connect
|
||||
// misclassifies a coincidental listener on a reused port. The decisive
|
||||
// signal is IDENTITY: the helper answers its authenticated /status
|
||||
// endpoint with the token server.json records; nothing else on that port
|
||||
// can. The probe is a spawned node one-liner so it works identically on
|
||||
// every platform.
|
||||
if (Number.isInteger(port) && port > 0 && token) {
|
||||
try {
|
||||
execFileSync(process.execPath, ['-e', [
|
||||
"const s = require('node:net').connect({ host: '127.0.0.1', port: Number(process.argv[1]), timeout: 800 });",
|
||||
"s.on('connect', () => { s.destroy(); process.exit(0); });",
|
||||
"s.on('timeout', () => { s.destroy(); process.exit(1); });",
|
||||
"s.on('error', () => process.exit(1));",
|
||||
].join(''), String(port)], { timeout: 3000, stdio: 'ignore' });
|
||||
"const req = require('node:http').get({ host: '127.0.0.1', port: Number(process.argv[1]), path: '/status?token=' + encodeURIComponent(process.argv[2]), timeout: 1200 }, (res) => { res.resume(); process.exit(res.statusCode === 200 ? 0 : 1); });",
|
||||
"req.on('timeout', () => { req.destroy(); process.exit(1); });",
|
||||
"req.on('error', () => process.exit(1));",
|
||||
].join(''), String(port), token], { timeout: 4000, stdio: 'ignore' });
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Legacy server.json without a port: best-effort process identity check.
|
||||
// Legacy server.json without a port/token: best-effort identity check.
|
||||
if (process.platform === 'win32') return true;
|
||||
try {
|
||||
const command = execFileSync('ps', ['-p', String(pid), '-o', 'command='], { encoding: 'utf-8' });
|
||||
|
||||
Reference in New Issue
Block a user