@smithers-orchestrator/accounts 0.21.0 → 0.23.0
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/package.json +2 -2
- package/src/defaultConfigDir.js +30 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smithers-orchestrator/accounts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Manage multiple Claude/Antigravity/Codex/Gemini/Kimi subscription and API-key accounts that Smithers agents can round-robin through.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"src/"
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@smithers-orchestrator/errors": "0.
|
|
23
|
+
"@smithers-orchestrator/errors": "0.23.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/bun": "latest",
|
package/src/defaultConfigDir.js
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SmithersError } from "@smithers-orchestrator/errors/SmithersError";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
2
3
|
import { accountsRoot } from "./accountsRoot.js";
|
|
3
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Account labels are used as a path segment under `~/.smithers/accounts`, so
|
|
7
|
+
* they must be a single, safe segment. This mirrors the wizard's input regex
|
|
8
|
+
* (`agentAddWizard.js`) and rejects anything that could escape the accounts
|
|
9
|
+
* root (`..`, `/`, `\`, etc.).
|
|
10
|
+
*/
|
|
11
|
+
const LABEL_PATTERN = /^[A-Za-z0-9._-]+$/;
|
|
12
|
+
|
|
4
13
|
/**
|
|
5
14
|
* Default location for a per-account CLI config dir, e.g.
|
|
6
15
|
* `~/.smithers/accounts/claude-work`.
|
|
@@ -10,5 +19,24 @@ import { accountsRoot } from "./accountsRoot.js";
|
|
|
10
19
|
* @returns {string}
|
|
11
20
|
*/
|
|
12
21
|
export function defaultConfigDir(label, env = process.env) {
|
|
13
|
-
|
|
22
|
+
if (typeof label !== "string" || !LABEL_PATTERN.test(label) || label === "." || label === "..") {
|
|
23
|
+
throw new SmithersError(
|
|
24
|
+
"ACCOUNT_INVALID",
|
|
25
|
+
`Invalid account label ${JSON.stringify(label)}: use only letters, digits, '.', '_' or '-' (no path separators or '..').`,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
const root = accountsRoot(env);
|
|
29
|
+
const dir = join(root, "accounts", label);
|
|
30
|
+
// Defense-in-depth: a valid label can never escape, but assert the resolved
|
|
31
|
+
// path stays under the accounts root so a future regex change can't silently
|
|
32
|
+
// reintroduce traversal.
|
|
33
|
+
const base = resolve(root, "accounts");
|
|
34
|
+
const resolved = resolve(dir);
|
|
35
|
+
if (resolved !== join(base, label) && !resolved.startsWith(base + "/")) {
|
|
36
|
+
throw new SmithersError(
|
|
37
|
+
"ACCOUNT_INVALID",
|
|
38
|
+
`Invalid account label ${JSON.stringify(label)}: resolved path escapes the accounts directory.`,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
return dir;
|
|
14
42
|
}
|