alvin-bot 4.4.2 → 4.4.3
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/CHANGELOG.md +11 -0
- package/dist/providers/registry.js +4 -3
- package/dist/services/sudo.js +28 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Alvin Bot are documented here.
|
|
4
4
|
|
|
5
|
+
## [4.4.3] — 2026-04-09
|
|
6
|
+
|
|
7
|
+
### 🔐 Security
|
|
8
|
+
- **Sudo password storage** — Fixed a vulnerability where the sudo password was passed to `/usr/bin/security` as a command-line argument, making it briefly visible in `ps aux` output during keychain writes. Password is now piped via stdin using the documented `-w` prompt mode (must be the last option, and the password is supplied twice for the interactive prompt + confirmation). Byte-exact round-trip verified for arbitrary special characters.
|
|
9
|
+
|
|
10
|
+
### 🛠 Providers
|
|
11
|
+
- **Gemini auto-registration narrowed** — The Google Gemini chat provider is no longer registered automatically just because `GOOGLE_API_KEY` is set. It is now registered only when `google` is referenced as the primary provider or in the fallback chain. The environment variable is still used for other Google-powered features (e.g. `/imagine` image generation) without forcing Gemini onto the chat provider list.
|
|
12
|
+
|
|
13
|
+
### 🧰 Tooling
|
|
14
|
+
- `package-lock.json` now tracks `package.json` version correctly.
|
|
15
|
+
|
|
5
16
|
## [2.2.0] — 2026-02-24
|
|
6
17
|
|
|
7
18
|
### 🔐 Security
|
|
@@ -185,12 +185,13 @@ export function createRegistry(config) {
|
|
|
185
185
|
model: "claude-opus-4-6",
|
|
186
186
|
};
|
|
187
187
|
}
|
|
188
|
-
//
|
|
189
|
-
|
|
188
|
+
// Register Google Gemini only if explicitly referenced as primary/fallback
|
|
189
|
+
// (GOOGLE_API_KEY is also used for image generation — doesn't mean Gemini should be a chat provider)
|
|
190
|
+
if (config.primary === "google" || config.fallbacks?.includes("google")) {
|
|
190
191
|
providers["google"] = {
|
|
191
192
|
...PROVIDER_PRESETS["gemini-2.5-flash"],
|
|
192
193
|
name: "Google Gemini",
|
|
193
|
-
apiKey: config.apiKeys
|
|
194
|
+
apiKey: config.apiKeys?.google,
|
|
194
195
|
};
|
|
195
196
|
}
|
|
196
197
|
// Always try to detect local Ollama
|
package/dist/services/sudo.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* - OS dialog handling (Accessibility, Full Disk Access, etc.)
|
|
12
12
|
* - Status check (is sudo configured? does it work?)
|
|
13
13
|
*/
|
|
14
|
-
import { execSync, spawn } from "child_process";
|
|
14
|
+
import { execSync, spawn, spawnSync } from "child_process";
|
|
15
15
|
import os from "os";
|
|
16
16
|
import fs from "fs";
|
|
17
17
|
import crypto from "crypto";
|
|
@@ -34,7 +34,33 @@ export function storePassword(password) {
|
|
|
34
34
|
execSync(`security delete-generic-password -a "${KEYCHAIN_ACCOUNT}" -s "${KEYCHAIN_SERVICE}" 2>/dev/null`, { stdio: "pipe" });
|
|
35
35
|
}
|
|
36
36
|
catch { /* didn't exist */ }
|
|
37
|
-
|
|
37
|
+
// Pipe password via stdin — NEVER pass it as an argv element,
|
|
38
|
+
// or it leaks into `ps aux` during the lifetime of the child process.
|
|
39
|
+
//
|
|
40
|
+
// From `man security`:
|
|
41
|
+
// "Use of the -p or -w options is insecure. Specify -w as the last
|
|
42
|
+
// option to be prompted."
|
|
43
|
+
//
|
|
44
|
+
// Requirements for this to work:
|
|
45
|
+
// 1. `-w` must be the LAST argument (otherwise security consumes
|
|
46
|
+
// the next argv element as the password).
|
|
47
|
+
// 2. The password must be written to stdin TWICE: once for the
|
|
48
|
+
// prompt, once for the "retype password" confirmation.
|
|
49
|
+
const result = spawnSync("security", [
|
|
50
|
+
"add-generic-password",
|
|
51
|
+
"-a", KEYCHAIN_ACCOUNT,
|
|
52
|
+
"-s", KEYCHAIN_SERVICE,
|
|
53
|
+
"-U",
|
|
54
|
+
"-w", // MUST be last — triggers interactive prompt reading from stdin
|
|
55
|
+
], {
|
|
56
|
+
input: password + "\n" + password + "\n", // prompt + confirm
|
|
57
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
58
|
+
timeout: 5000,
|
|
59
|
+
});
|
|
60
|
+
if (result.status !== 0) {
|
|
61
|
+
const stderr = result.stderr?.toString().trim() || `exit ${result.status}`;
|
|
62
|
+
throw new Error(stderr);
|
|
63
|
+
}
|
|
38
64
|
return { ok: true, method: "macOS Keychain" };
|
|
39
65
|
}
|
|
40
66
|
else {
|