@livedesk/client 0.1.238 → 0.1.240
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -251,7 +251,7 @@ async function waitForClientUpdateShutdownSignal(
|
|
|
251
251
|
return { ready: false, error };
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
-
function markClientUpdateConnected() {
|
|
254
|
+
function markClientUpdateConnected() {
|
|
255
255
|
const operationId = String(process.env.LIVEDESK_CLIENT_UPDATE_OPERATION_ID || '').trim();
|
|
256
256
|
if (!operationId) return;
|
|
257
257
|
void writeClientUpdateState('connected', {
|
|
@@ -262,8 +262,59 @@ function markClientUpdateConnected() {
|
|
|
262
262
|
error: ''
|
|
263
263
|
}).catch(error => {
|
|
264
264
|
console.error(`LiveDesk client update diagnostics could not be persisted: ${error?.message || error}`);
|
|
265
|
-
});
|
|
266
|
-
}
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
async function publishClientUpdateSupervisorProof(socket) {
|
|
269
|
+
const operationId = String(process.env.LIVEDESK_CLIENT_UPDATE_OPERATION_ID || '').trim();
|
|
270
|
+
const attemptId = String(process.env.LIVEDESK_CLIENT_UPDATE_ATTEMPT_ID || '').trim();
|
|
271
|
+
const expectedLauncherPid = Number(process.env.LIVEDESK_CLIENT_PARENT_PID || 0);
|
|
272
|
+
if (!operationId || !attemptId || !Number.isInteger(expectedLauncherPid) || expectedLauncherPid <= 1) return;
|
|
273
|
+
const deadline = Date.now() + 60_000;
|
|
274
|
+
while (Date.now() < deadline && !socket.destroyed) {
|
|
275
|
+
try {
|
|
276
|
+
const state = JSON.parse(await fs.readFile(getClientUpdateStatePath(), 'utf8'));
|
|
277
|
+
if (String(state?.operationId || '') !== operationId
|
|
278
|
+
|| String(state?.attemptId || '') !== attemptId) {
|
|
279
|
+
await wait(100);
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (['failed', 'restored', 'cancelled'].includes(String(state.stage || ''))) return;
|
|
283
|
+
const launcherPid = Number(state.launcherPid || 0);
|
|
284
|
+
const agentPid = Number(state.agentPid || 0);
|
|
285
|
+
const supervisorPid = Number(state.supervisorPid || 0);
|
|
286
|
+
const completedAt = String(state.completedAt || '').trim();
|
|
287
|
+
const exactSupervisorCompletion = state.stage === 'connected'
|
|
288
|
+
&& state.restartVerified === true
|
|
289
|
+
&& Number.isFinite(Date.parse(completedAt))
|
|
290
|
+
&& launcherPid === expectedLauncherPid
|
|
291
|
+
&& agentPid === process.pid
|
|
292
|
+
&& Number.isInteger(supervisorPid)
|
|
293
|
+
&& supervisorPid > 1
|
|
294
|
+
&& String(state.productVersion || '') === PRODUCT_VERSION
|
|
295
|
+
&& String(state.agentVersion || '') === AGENT_VERSION
|
|
296
|
+
&& String(state.targetProductVersion || '') === PRODUCT_VERSION
|
|
297
|
+
&& String(state.targetAgentVersion || state.targetVersion || '') === AGENT_VERSION;
|
|
298
|
+
if (exactSupervisorCompletion) {
|
|
299
|
+
writeJsonLine(socket, {
|
|
300
|
+
type: 'client.update.verified',
|
|
301
|
+
operationId,
|
|
302
|
+
attemptId,
|
|
303
|
+
launcherPid,
|
|
304
|
+
agentPid,
|
|
305
|
+
supervisorPid,
|
|
306
|
+
productVersion: PRODUCT_VERSION,
|
|
307
|
+
agentVersion: AGENT_VERSION,
|
|
308
|
+
completedAt
|
|
309
|
+
});
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
} catch {
|
|
313
|
+
// The exact package supervisor may be replacing the atomic state file.
|
|
314
|
+
}
|
|
315
|
+
await wait(100);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
267
318
|
|
|
268
319
|
function printHelp() {
|
|
269
320
|
console.log(`
|
|
@@ -1972,9 +2023,10 @@ function connectOnce(options, deviceId) {
|
|
|
1972
2023
|
remoteFiles: true,
|
|
1973
2024
|
fileTransferMaxBytes: MAX_FILE_TRANSFER_BYTES,
|
|
1974
2025
|
computerAgent: options.taskEnabled,
|
|
1975
|
-
taskDispatch: options.taskEnabled,
|
|
1976
|
-
clientUpdate: true,
|
|
1977
|
-
|
|
2026
|
+
taskDispatch: options.taskEnabled,
|
|
2027
|
+
clientUpdate: true,
|
|
2028
|
+
clientUpdateVerifiedProof: true,
|
|
2029
|
+
productVersion: PRODUCT_VERSION,
|
|
1978
2030
|
agentApproval: options.taskEnabled,
|
|
1979
2031
|
agentAudit: options.taskEnabled,
|
|
1980
2032
|
agentTools: [...NODE_AGENT_OPERATIONS],
|
|
@@ -2000,8 +2052,13 @@ function connectOnce(options, deviceId) {
|
|
|
2000
2052
|
options.effectivePolicy = message.effectivePolicy && typeof message.effectivePolicy === 'object'
|
|
2001
2053
|
? message.effectivePolicy
|
|
2002
2054
|
: null;
|
|
2003
|
-
console.log(`Connected to LiveDesk Hub as ${options.name} (${deviceId})`);
|
|
2004
|
-
markClientUpdateConnected();
|
|
2055
|
+
console.log(`Connected to LiveDesk Hub as ${options.name} (${deviceId})`);
|
|
2056
|
+
markClientUpdateConnected();
|
|
2057
|
+
void publishClientUpdateSupervisorProof(socket).catch(error => {
|
|
2058
|
+
if (!socket.destroyed) {
|
|
2059
|
+
console.error(`LiveDesk client update verification proof failed: ${error?.message || error}`);
|
|
2060
|
+
}
|
|
2061
|
+
});
|
|
2005
2062
|
writeJsonLine(socket, {
|
|
2006
2063
|
type: 'status',
|
|
2007
2064
|
status: getStatus(options)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livedesk/client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.240",
|
|
4
4
|
"description": "LiveDesk local remote client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"ws": "^8.18.3"
|
|
43
43
|
},
|
|
44
44
|
"optionalDependencies": {
|
|
45
|
-
"@livedesk/fast-linux-x64": "0.1.
|
|
46
|
-
"@livedesk/fast-osx-arm64": "0.1.
|
|
47
|
-
"@livedesk/fast-osx-x64": "0.1.
|
|
48
|
-
"@livedesk/fast-win-x64": "0.1.
|
|
45
|
+
"@livedesk/fast-linux-x64": "0.1.439",
|
|
46
|
+
"@livedesk/fast-osx-arm64": "0.1.439",
|
|
47
|
+
"@livedesk/fast-osx-x64": "0.1.439",
|
|
48
|
+
"@livedesk/fast-win-x64": "0.1.439"
|
|
49
49
|
},
|
|
50
50
|
"publishConfig": {
|
|
51
51
|
"access": "public"
|
|
@@ -1022,10 +1022,9 @@ function isLoopbackRequest(req) {
|
|
|
1022
1022
|
return address === '127.0.0.1' || address === '::1' || address === 'localhost' || !address;
|
|
1023
1023
|
}
|
|
1024
1024
|
|
|
1025
|
-
function isTrustedApiOrigin(value, trustedWebOrigins) {
|
|
1026
|
-
const rawOrigin = normalizeString(value, 300);
|
|
1027
|
-
|
|
1028
|
-
const origin = normalizeOrigin(rawOrigin);
|
|
1025
|
+
function isTrustedApiOrigin(value, trustedWebOrigins) {
|
|
1026
|
+
const rawOrigin = normalizeString(value, 300);
|
|
1027
|
+
const origin = normalizeOrigin(rawOrigin);
|
|
1029
1028
|
if (!origin) return false;
|
|
1030
1029
|
if (trustedWebOrigins.has(origin)) return true;
|
|
1031
1030
|
try {
|
|
@@ -1049,11 +1048,10 @@ function isTrustedLocalRequest(req, host, port, options = {}) {
|
|
|
1049
1048
|
const requestHost = normalizeString(req.headers.host, 300).split(':')[0].toLowerCase();
|
|
1050
1049
|
if (requestHost && requestHost !== host.toLowerCase() && requestHost !== 'localhost' && requestHost !== '127.0.0.1') return false;
|
|
1051
1050
|
|
|
1052
|
-
// Chromium can mark modulepreload/stylesheet requests as cross-site
|
|
1053
|
-
//
|
|
1054
|
-
//
|
|
1055
|
-
//
|
|
1056
|
-
// remain protected by the CSRF token check below.
|
|
1051
|
+
// Chromium can mark modulepreload/stylesheet requests as cross-site. Static
|
|
1052
|
+
// assets are not privileged. An opaque Origin (`null`) is never accepted for
|
|
1053
|
+
// an API route because it cannot distinguish the LiveDesk shell from an
|
|
1054
|
+
// attacker-controlled file, sandbox, or data page.
|
|
1057
1055
|
if (options.allowStaticCrossSite === true) {
|
|
1058
1056
|
return true;
|
|
1059
1057
|
}
|
|
@@ -1073,10 +1071,9 @@ function isTrustedLocalRequest(req, host, port, options = {}) {
|
|
|
1073
1071
|
|| fetchSite === 'none';
|
|
1074
1072
|
}
|
|
1075
1073
|
|
|
1076
|
-
function resolveCorsOrigin(requestOrigin, port, trustedWebOrigins) {
|
|
1077
|
-
const origin = normalizeString(requestOrigin, 300);
|
|
1078
|
-
|
|
1079
|
-
return origin && isTrustedApiOrigin(origin, trustedWebOrigins)
|
|
1074
|
+
function resolveCorsOrigin(requestOrigin, port, trustedWebOrigins) {
|
|
1075
|
+
const origin = normalizeString(requestOrigin, 300);
|
|
1076
|
+
return origin && isTrustedApiOrigin(origin, trustedWebOrigins)
|
|
1080
1077
|
? normalizeOrigin(origin)
|
|
1081
1078
|
: `http://127.0.0.1:${port}`;
|
|
1082
1079
|
}
|