@mnemonik/cli 7.104.1 → 7.104.4
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.
- package/dist/auth/credentials.js +11 -6
- package/dist/bin.js +5 -4
- package/dist/bin.js.map +1 -1
- package/dist/diagnostics.js +11 -6
- package/dist/digests.json +68 -64
- package/dist/humanReason.d.ts +19 -0
- package/dist/humanReason.d.ts.map +1 -0
- package/dist/humanReason.js +220 -0
- package/dist/humanReason.js.map +1 -0
- package/dist/identity/migrate.js +8 -2
- package/dist/install/journal.js +8 -2
- package/dist/install/journey.d.ts.map +1 -1
- package/dist/install/journey.js +48 -23
- package/dist/install/journey.js.map +1 -1
- package/dist/install/ownership.js +8 -2
- package/dist/install/ui.d.ts.map +1 -1
- package/dist/install/ui.js +3 -2
- package/dist/install/ui.js.map +1 -1
- package/dist/installSession.d.ts.map +1 -1
- package/dist/installSession.js +3 -2
- package/dist/installSession.js.map +1 -1
- package/dist/installation.js +8 -2
- package/dist/launcher.js +8 -2
- package/dist/output.d.ts +1 -1
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +4 -2
- package/dist/output.js.map +1 -1
- package/dist/preflight.d.ts +1 -0
- package/dist/preflight.d.ts.map +1 -1
- package/dist/preflight.js +23 -22
- package/dist/preflight.js.map +1 -1
- package/dist/project/records.js +8 -2
- package/dist/project.d.ts +2 -0
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +41 -28
- package/dist/project.js.map +1 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +36 -39
- package/dist/router.js.map +1 -1
- package/dist/runtime/bootstrap.d.ts.map +1 -1
- package/dist/runtime/bootstrap.js +57 -9
- package/dist/runtime/bootstrap.js.map +1 -1
- package/dist/runtime/selfUpdate.d.ts.map +1 -1
- package/dist/runtime/selfUpdate.js +10 -3
- package/dist/runtime/selfUpdate.js.map +1 -1
- package/dist/runtime/signers.js +67 -39
- package/dist/runtime/store.js +40 -12
- package/dist/runtime/store.js.map +1 -1
- package/dist/sbom.json +21 -21
- package/dist/scanner/control.js +8 -2
- package/dist/scanner/discover.d.ts.map +1 -1
- package/dist/scanner/discover.js +17 -17
- package/dist/scanner/discover.js.map +1 -1
- package/dist/scanner/enable.js +10 -4
- package/dist/scanner/enable.js.map +1 -1
- package/dist/scanner/picker.d.ts.map +1 -1
- package/dist/scanner/picker.js +2 -6
- package/dist/scanner/picker.js.map +1 -1
- package/dist/scanner/update.js +8 -2
- package/dist/scanner-release.json +25 -25
- package/dist/screens/journey.d.ts.map +1 -1
- package/dist/screens/journey.js +0 -1
- package/dist/screens/journey.js.map +1 -1
- package/dist/status.d.ts +1 -4
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +2 -138
- package/dist/status.js.map +1 -1
- package/dist/vendor/local-setup.js +19 -5
- package/dist/vendor/shared/runtimeSigners.js +65 -19
- package/package.json +31 -31
|
@@ -4,6 +4,7 @@ import { basename, dirname, join, resolve, sep, win32 } from 'node:path';
|
|
|
4
4
|
import { createHash, createPublicKey, randomUUID, timingSafeEqual, verify as verifySignature, } from 'node:crypto';
|
|
5
5
|
import { execFile, execFileSync } from 'node:child_process';
|
|
6
6
|
import { promisify } from 'node:util';
|
|
7
|
+
import { hostname } from 'node:os';
|
|
7
8
|
export const execute = (file, args, input) => {
|
|
8
9
|
const result = promisify(execFile)(file, args);
|
|
9
10
|
if (input === undefined)
|
|
@@ -140,11 +141,12 @@ export async function verifyWindowsAcl(path, run = hookExecute, state) {
|
|
|
140
141
|
if (!privateEntries((await drive(saveAcl(path, false, [path], state), run)).get(path), user, false))
|
|
141
142
|
throw new Error('acl_permissions');
|
|
142
143
|
}
|
|
143
|
-
const aclArgs = (path, sid) => [
|
|
144
|
+
const aclArgs = (path, sid, created = false) => [
|
|
144
145
|
path,
|
|
145
146
|
'/inheritance:r',
|
|
146
147
|
'/grant:r',
|
|
147
148
|
`*${sid}:(OI)(CI)F`,
|
|
149
|
+
...(created ? ['/remove:g', '*S-1-5-32-544', '*S-1-5-18'] : []),
|
|
148
150
|
];
|
|
149
151
|
// Keep injected runners at the logical-command boundary; native execution owns encoding.
|
|
150
152
|
function hookInvocation(file, args) {
|
|
@@ -223,7 +225,10 @@ function privateEntries(entries, user, directory) {
|
|
|
223
225
|
const ace = /^\(([AD]);((?:OI|CI|NP|IO|ID|SA|FA)*);[A-Za-z0-9]+;;;((?:S-1-(?:\d+-)+\d+)|[A-Z]{2})\)$/.exec(line);
|
|
224
226
|
if (!ace)
|
|
225
227
|
throw new Error('acl_unavailable');
|
|
226
|
-
|
|
228
|
+
const ownAlias = ace[3] === 'LA' &&
|
|
229
|
+
user.sid.endsWith('-500') &&
|
|
230
|
+
user.name.toLowerCase().startsWith(hostname().toLowerCase() + '\\');
|
|
231
|
+
return ((!directory || !ace[2]?.includes('ID')) && (ace[1] === 'D' || ace[3] === user.sid || ownAlias));
|
|
227
232
|
});
|
|
228
233
|
}
|
|
229
234
|
const auditDirectories = new Set();
|
|
@@ -249,7 +254,7 @@ function* prepareAclDirectory(state) {
|
|
|
249
254
|
throw new Error('acl_permissions');
|
|
250
255
|
if (!auditDirectories.has(directory)) {
|
|
251
256
|
currentIdentity ??= readIdentity(yield [windowsCommand('whoami.exe'), identityArgs]);
|
|
252
|
-
yield [windowsCommand('icacls.exe'), aclArgs(directory, currentIdentity.sid)];
|
|
257
|
+
yield [windowsCommand('icacls.exe'), aclArgs(directory, currentIdentity.sid, created)];
|
|
253
258
|
if (!created) {
|
|
254
259
|
const temp = join(directory, `.acl-${randomUUID()}.tmp`);
|
|
255
260
|
writeFileSync(temp, '', { flag: 'wx', mode: 0o600 });
|
|
@@ -319,14 +324,21 @@ function dirEntry(line) {
|
|
|
319
324
|
return owner && name ? { owner, name } : undefined;
|
|
320
325
|
}
|
|
321
326
|
const unknownOwner = (owner, user) => user.name.length >= ownerWidth || owner.length >= ownerWidth || owner.includes('...');
|
|
322
|
-
function ownerLookup(paths) {
|
|
327
|
+
function ownerLookup(paths, restoreOwner) {
|
|
323
328
|
if (paths.some((path) => /[\t\r\n]/.test(path)))
|
|
324
329
|
throw new Error('acl_path_unavailable');
|
|
325
330
|
const script = `$ErrorActionPreference = 'Stop'
|
|
326
331
|
[Console]::InputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
327
332
|
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
328
333
|
while ($null -ne ($path = [Console]::ReadLine())) {
|
|
329
|
-
$
|
|
334
|
+
${restoreOwner
|
|
335
|
+
? `$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
|
|
336
|
+
if ($identity.User.Value -eq ${quote(restoreOwner)} -and $identity.Owner.Value -eq 'S-1-5-32-544') {
|
|
337
|
+
& ${quote(windowsCommand('icacls.exe'))} $path /setowner ${quote('*' + restoreOwner)} /l | Out-Null
|
|
338
|
+
if ($LASTEXITCODE -ne 0) { throw 'acl_owner' }
|
|
339
|
+
}`
|
|
340
|
+
: ''}
|
|
341
|
+
$owner = [System.IO.File]::GetAccessControl($path).GetOwner([System.Security.Principal.SecurityIdentifier]).Value
|
|
330
342
|
[Console]::WriteLine($path + "\`t" + $owner)
|
|
331
343
|
}`;
|
|
332
344
|
return [
|
|
@@ -395,16 +407,28 @@ function* hookPermission(path, created, session, directory = true) {
|
|
|
395
407
|
return entry?.name.toLowerCase() === basename(path).toLowerCase() ? [entry.owner] : [];
|
|
396
408
|
});
|
|
397
409
|
let owner = owners[0];
|
|
398
|
-
|
|
410
|
+
const currentOwner = () => [user.name.toLowerCase(), user.sid.toLowerCase()].includes(owner ?? '');
|
|
411
|
+
if (owners.length === 1 &&
|
|
412
|
+
owner &&
|
|
413
|
+
(unknownOwner(owner, user) || (!currentOwner() && !/^s-1-(?:\d+-)+\d+$/.test(owner))))
|
|
399
414
|
owner = ownerSids(yield ownerLookup([path])).get(path);
|
|
400
|
-
|
|
401
|
-
|
|
415
|
+
const elevatedOwner = owner === 's-1-5-32-544';
|
|
416
|
+
if (owners.length !== 1 || (!currentOwner() && !elevatedOwner))
|
|
402
417
|
throw new Error('acl_owner');
|
|
403
418
|
const icacls = windowsCommand('icacls.exe');
|
|
404
419
|
if (created)
|
|
405
|
-
yield [icacls, aclArgs(path, user.sid)];
|
|
420
|
+
yield [icacls, aclArgs(path, user.sid, true)];
|
|
406
421
|
let valid = privateEntries((yield* saveAcl(path, false)).get(path), user, directory);
|
|
407
|
-
if (
|
|
422
|
+
if (elevatedOwner) {
|
|
423
|
+
// Existing group-owned paths must already be private. Only a freshly created
|
|
424
|
+
// directory may have its inherited ACL constrained before restoring its owner.
|
|
425
|
+
if (!valid)
|
|
426
|
+
throw new Error('acl_permissions');
|
|
427
|
+
owner = ownerSids(yield ownerLookup([path], user.sid)).get(path);
|
|
428
|
+
if (!currentOwner())
|
|
429
|
+
throw new Error('acl_owner');
|
|
430
|
+
}
|
|
431
|
+
else if (!valid && !created && directory) {
|
|
408
432
|
yield [icacls, aclArgs(path, user.sid)];
|
|
409
433
|
valid = privateEntries((yield* saveAcl(path, false)).get(path), user, directory);
|
|
410
434
|
}
|
|
@@ -424,10 +448,6 @@ function* hookPermission(path, created, session, directory = true) {
|
|
|
424
448
|
/* A missing receipt costs another audit next process. */
|
|
425
449
|
}
|
|
426
450
|
}
|
|
427
|
-
export async function windowsCurrentUserDirectoryAcl(path, run = hookExecute) {
|
|
428
|
-
currentIdentity ??= readIdentity(stdout(await run(windowsCommand('whoami.exe'), identityArgs)));
|
|
429
|
-
await run(windowsCommand('icacls.exe'), aclArgs(path, currentIdentity.sid));
|
|
430
|
-
}
|
|
431
451
|
export async function protectWindowsDirectory(path, created, run = hookExecute, session = path) {
|
|
432
452
|
await drive(hookPermission(path, created, session), run);
|
|
433
453
|
}
|
|
@@ -493,14 +513,40 @@ export async function auditWindowsPermissions(state, paths, run = hookExecute, r
|
|
|
493
513
|
}
|
|
494
514
|
const verdicts = new Map();
|
|
495
515
|
const ownerPaths = [...owners.keys()].filter((path) => path === root || path.startsWith(root + sep));
|
|
496
|
-
const
|
|
497
|
-
|
|
498
|
-
|
|
516
|
+
const records = await drive(saveAcl(root, recursive, ownerPaths, tempState), run);
|
|
517
|
+
// Elevated Windows tokens create Administrators-owned files even with a private
|
|
518
|
+
// user DACL. Restore the exact-user invariant, including a failed install's
|
|
519
|
+
// directories, only after proving both the owner SID and the existing DACL.
|
|
520
|
+
const candidates = [...records]
|
|
521
|
+
.filter(([path, entries]) => {
|
|
522
|
+
const owner = owners.get(path);
|
|
523
|
+
if (!owner || owner === user.name.toLowerCase() || owner === user.sid.toLowerCase())
|
|
524
|
+
return false;
|
|
525
|
+
try {
|
|
526
|
+
return privateEntries(entries, user, false);
|
|
527
|
+
}
|
|
528
|
+
catch {
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
531
|
+
})
|
|
532
|
+
.map(([path]) => path);
|
|
533
|
+
const lookup = new Set([
|
|
534
|
+
...ownerPaths.filter((path) => owners.get(path)?.includes('...')),
|
|
535
|
+
...candidates,
|
|
536
|
+
]);
|
|
537
|
+
if (lookup.size) {
|
|
538
|
+
const result = await run(...ownerLookup([...lookup])).catch(() => ({ stdout: '' }));
|
|
499
539
|
for (const [path, sid] of ownerSids(stdout(result)))
|
|
500
|
-
if (
|
|
540
|
+
if (lookup.has(path))
|
|
501
541
|
owners.set(path, sid);
|
|
542
|
+
const elevated = candidates.filter((path) => owners.get(path) === 's-1-5-32-544');
|
|
543
|
+
if (elevated.length) {
|
|
544
|
+
const restored = ownerSids(stdout(await run(...ownerLookup(elevated, user.sid))));
|
|
545
|
+
for (const path of elevated)
|
|
546
|
+
owners.set(path, restored.get(path) ?? '...');
|
|
547
|
+
}
|
|
502
548
|
}
|
|
503
|
-
for (const [path, entries] of
|
|
549
|
+
for (const [path, entries] of records) {
|
|
504
550
|
const owner = owners.get(path) ?? '...';
|
|
505
551
|
const owned = owner === user.name.toLowerCase() || owner === user.sid.toLowerCase();
|
|
506
552
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mnemonik/cli",
|
|
3
|
-
"version": "7.104.
|
|
3
|
+
"version": "7.104.4",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/JayDeeCo-Limited/mnemonik-cli.git"
|
|
@@ -34,27 +34,27 @@
|
|
|
34
34
|
"hosts": {
|
|
35
35
|
"claude-code": {
|
|
36
36
|
"package": "@mnemonik/claude-code-hooks",
|
|
37
|
-
"version": "0.9.
|
|
37
|
+
"version": "0.9.214",
|
|
38
38
|
"closure": [
|
|
39
39
|
{
|
|
40
40
|
"name": "@mnemonik/claude-code-hooks",
|
|
41
|
-
"version": "0.9.
|
|
42
|
-
"integrity": "sha512-
|
|
41
|
+
"version": "0.9.214",
|
|
42
|
+
"integrity": "sha512-85PiXD51d79WbF61NE+QgFB2kjgR1HYxZjAANUmAYRLTh2PVTmtje+OpVsDC47WJsjdcTZl+EO7SrKq8qDZUqw=="
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
"name": "@mnemonik/credentials",
|
|
46
|
-
"version": "0.1.
|
|
47
|
-
"integrity": "sha512-
|
|
46
|
+
"version": "0.1.35",
|
|
47
|
+
"integrity": "sha512-XiwRlIABOKrEnOAO+MnBWZQjXPbsi0uC4Qm3Dlge7hsA1Uh69e+1S7KIwp38lv+3nIVUmPXo26ja8xp8oemmcw=="
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
"name": "@mnemonik/local-setup",
|
|
51
|
-
"version": "0.1.
|
|
52
|
-
"integrity": "sha512-
|
|
51
|
+
"version": "0.1.35",
|
|
52
|
+
"integrity": "sha512-Tddt66qAvGF7xxTrXQwY7Jyc13rJcLbpYJtyy49PEvWBGPD5k7+nbs2/SDcvMvakPDfLIUdVCoRWfgK6pIYoBQ=="
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"name": "@mnemonik/shared",
|
|
56
|
-
"version": "7.104.
|
|
57
|
-
"integrity": "sha512-
|
|
56
|
+
"version": "7.104.4",
|
|
57
|
+
"integrity": "sha512-PakAp+aTma4MX8hwCs+Jkg1QiEuSKQPiEG6Cc16mkqOW4kYbS07JCZ93E69doUGrR4xBpbDw1l6iMTMUCaY6TQ=="
|
|
58
58
|
},
|
|
59
59
|
{
|
|
60
60
|
"name": "ignore",
|
|
@@ -87,31 +87,31 @@
|
|
|
87
87
|
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
|
88
88
|
}
|
|
89
89
|
],
|
|
90
|
-
"releaseVersion": "7.104.
|
|
90
|
+
"releaseVersion": "7.104.4"
|
|
91
91
|
},
|
|
92
92
|
"codex": {
|
|
93
93
|
"package": "@mnemonik/codex-hooks",
|
|
94
|
-
"version": "0.8.
|
|
94
|
+
"version": "0.8.183",
|
|
95
95
|
"closure": [
|
|
96
96
|
{
|
|
97
97
|
"name": "@mnemonik/codex-hooks",
|
|
98
|
-
"version": "0.8.
|
|
99
|
-
"integrity": "sha512-
|
|
98
|
+
"version": "0.8.183",
|
|
99
|
+
"integrity": "sha512-QXpQC7gW0sQ0WVgyxMXv87kztFPN26iAcNgGPPF3bsIsV264BGEwvRqPZ8UvctnA41nU56tXFs5vZ/lrFb40lA=="
|
|
100
100
|
},
|
|
101
101
|
{
|
|
102
102
|
"name": "@mnemonik/credentials",
|
|
103
|
-
"version": "0.1.
|
|
104
|
-
"integrity": "sha512-
|
|
103
|
+
"version": "0.1.35",
|
|
104
|
+
"integrity": "sha512-XiwRlIABOKrEnOAO+MnBWZQjXPbsi0uC4Qm3Dlge7hsA1Uh69e+1S7KIwp38lv+3nIVUmPXo26ja8xp8oemmcw=="
|
|
105
105
|
},
|
|
106
106
|
{
|
|
107
107
|
"name": "@mnemonik/local-setup",
|
|
108
|
-
"version": "0.1.
|
|
109
|
-
"integrity": "sha512-
|
|
108
|
+
"version": "0.1.35",
|
|
109
|
+
"integrity": "sha512-Tddt66qAvGF7xxTrXQwY7Jyc13rJcLbpYJtyy49PEvWBGPD5k7+nbs2/SDcvMvakPDfLIUdVCoRWfgK6pIYoBQ=="
|
|
110
110
|
},
|
|
111
111
|
{
|
|
112
112
|
"name": "@mnemonik/shared",
|
|
113
|
-
"version": "7.104.
|
|
114
|
-
"integrity": "sha512-
|
|
113
|
+
"version": "7.104.4",
|
|
114
|
+
"integrity": "sha512-PakAp+aTma4MX8hwCs+Jkg1QiEuSKQPiEG6Cc16mkqOW4kYbS07JCZ93E69doUGrR4xBpbDw1l6iMTMUCaY6TQ=="
|
|
115
115
|
},
|
|
116
116
|
{
|
|
117
117
|
"name": "ignore",
|
|
@@ -144,31 +144,31 @@
|
|
|
144
144
|
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
|
145
145
|
}
|
|
146
146
|
],
|
|
147
|
-
"releaseVersion": "7.104.
|
|
147
|
+
"releaseVersion": "7.104.4"
|
|
148
148
|
},
|
|
149
149
|
"cursor": {
|
|
150
150
|
"package": "@mnemonik/cursor-hooks",
|
|
151
|
-
"version": "0.7.
|
|
151
|
+
"version": "0.7.170",
|
|
152
152
|
"closure": [
|
|
153
153
|
{
|
|
154
154
|
"name": "@mnemonik/cursor-hooks",
|
|
155
|
-
"version": "0.7.
|
|
156
|
-
"integrity": "sha512
|
|
155
|
+
"version": "0.7.170",
|
|
156
|
+
"integrity": "sha512-k6c2nfnkB8aStT/dQP56WaFgVU/r1OeKrMdz+SKB65NpnIhWvpu+iKngLWM9SaLo5OslG6Qcc4ttr8Z/yesTQg=="
|
|
157
157
|
},
|
|
158
158
|
{
|
|
159
159
|
"name": "@mnemonik/credentials",
|
|
160
|
-
"version": "0.1.
|
|
161
|
-
"integrity": "sha512-
|
|
160
|
+
"version": "0.1.35",
|
|
161
|
+
"integrity": "sha512-XiwRlIABOKrEnOAO+MnBWZQjXPbsi0uC4Qm3Dlge7hsA1Uh69e+1S7KIwp38lv+3nIVUmPXo26ja8xp8oemmcw=="
|
|
162
162
|
},
|
|
163
163
|
{
|
|
164
164
|
"name": "@mnemonik/local-setup",
|
|
165
|
-
"version": "0.1.
|
|
166
|
-
"integrity": "sha512-
|
|
165
|
+
"version": "0.1.35",
|
|
166
|
+
"integrity": "sha512-Tddt66qAvGF7xxTrXQwY7Jyc13rJcLbpYJtyy49PEvWBGPD5k7+nbs2/SDcvMvakPDfLIUdVCoRWfgK6pIYoBQ=="
|
|
167
167
|
},
|
|
168
168
|
{
|
|
169
169
|
"name": "@mnemonik/shared",
|
|
170
|
-
"version": "7.104.
|
|
171
|
-
"integrity": "sha512-
|
|
170
|
+
"version": "7.104.4",
|
|
171
|
+
"integrity": "sha512-PakAp+aTma4MX8hwCs+Jkg1QiEuSKQPiEG6Cc16mkqOW4kYbS07JCZ93E69doUGrR4xBpbDw1l6iMTMUCaY6TQ=="
|
|
172
172
|
},
|
|
173
173
|
{
|
|
174
174
|
"name": "ignore",
|
|
@@ -201,7 +201,7 @@
|
|
|
201
201
|
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
|
202
202
|
}
|
|
203
203
|
],
|
|
204
|
-
"releaseVersion": "7.104.
|
|
204
|
+
"releaseVersion": "7.104.4"
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
207
|
}
|