instabox 0.5.3 → 0.5.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/bin/instabox.mjs CHANGED
@@ -23,7 +23,7 @@ import { orderBoxes } from '../lib/boxes.mjs';
23
23
  import { guestUserNote, localGuestUser } from '../lib/guestuser.mjs';
24
24
  import { checkCli, findCli, installCli, installCommand, isOnboarding, real, runCli } from '../lib/cli.mjs';
25
25
  import { browserCommand, callbackHandler } from '../lib/login.mjs';
26
- import { sessionArgs } from '../lib/ssh.mjs';
26
+ import { makeDirPrivate, sessionArgs } from '../lib/ssh.mjs';
27
27
  import { loadCredentials, saveCredentials } from '../lib/credentials.mjs';
28
28
 
29
29
  // Same variables, same order as the instabox CLI, so both talk to one server.
@@ -448,6 +448,8 @@ async function onboard(wantBox) {
448
448
  rmSync(dir, { recursive: true, force: true });
449
449
  } catch {}
450
450
  });
451
+ // before ssh-keygen, so the key inherits only the owner's access
452
+ if (!makeDirPrivate(dir)) console.log(dim(` could not make ${dir} private (icacls failed); ssh may refuse the key`));
451
453
  const key = join(dir, 'id_ed25519');
452
454
  const kg = spawnSync('ssh-keygen', ['-q', '-t', 'ed25519', '-N', '', '-C', 'instabox', '-f', key], {
453
455
  stdio: 'ignore',
package/lib/cli.mjs CHANGED
@@ -201,7 +201,7 @@ async function installWindows(
201
201
  version: v,
202
202
  pathHint: onPath
203
203
  ? null
204
- : `[Environment]::SetEnvironmentVariable('Path', [Environment]::GetEnvironmentVariable('Path', 'User') + ';${to.replaceAll("'", "''")}', 'User')`,
204
+ : `[Environment]::SetEnvironmentVariable('Path', ([string][Environment]::GetEnvironmentVariable('Path', 'User')).TrimEnd(';') + ';${to.replaceAll("'", "''")}', 'User')`,
205
205
  };
206
206
  } catch (e) {
207
207
  rmSync(tmp, { force: true });
package/lib/ssh.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  // ssh's argv for a session with this run's throwaway key, certificate and known_hosts.
2
+ import { spawnSync } from 'node:child_process';
2
3
  import { join } from 'node:path';
3
4
 
4
5
  // ssh splits an -o value at whitespace and reads ' as an open quote; Windows profile paths often have either.
@@ -24,3 +25,12 @@ export function sessionArgs({ dir, key, port, username, host }) {
24
25
  `${username}@${host}`,
25
26
  ];
26
27
  }
28
+
29
+ // Windows OpenSSH rejects a key that anyone but its owner may read, and a temp dir can pass on other users' ACEs.
30
+ export function makeDirPrivate(dir, { platform = process.platform, run = spawnSync } = {}) {
31
+ if (platform !== 'win32') return true;
32
+ const who = run('whoami', ['/user', '/fo', 'csv', '/nh'], { encoding: 'utf8' });
33
+ const sid = String(who.stdout || '').match(/"(S-1-[0-9-]+)"/)?.[1];
34
+ if (!sid) return false;
35
+ return run('icacls', [dir, '/inheritance:r', '/grant:r', `*${sid}:(OI)(CI)F`], { stdio: 'ignore' }).status === 0;
36
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instabox",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "A cloud box for your coding agent, the instabox CLI and its agent skills in one command: npx instabox@latest",
5
5
  "type": "module",
6
6
  "bin": {