mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-07 22:44:16 +00:00
Secrets: add inline allowlist review set (#38314)
* Secrets: add inline allowlist review set * Secrets: narrow detect-secrets file exclusions * Secrets: exclude Docker fingerprint false positive * Secrets: allowlist test and docs false positives * Secrets: refresh baseline after allowlist updates * Secrets: fix gateway chat fixture pragma * Secrets: format pre-commit config * Android: keep talk mode fixture JSON valid * Feishu: rely on client timeout injection * Secrets: allowlist provider auth test fixtures * Secrets: allowlist onboard search fixtures * Secrets: allowlist onboard mode fixture * Secrets: allowlist gateway auth mode fixture * Secrets: allowlist APNS wake test key * Secrets: allowlist gateway reload fixtures * Secrets: allowlist moonshot video fixture * Secrets: allowlist auto audio fixture * Secrets: allowlist tiny audio fixture * Secrets: allowlist embeddings fixtures * Secrets: allowlist resolve fixtures * Secrets: allowlist target registry pattern fixtures * Secrets: allowlist gateway chat env fixture * Secrets: refresh baseline after fixture allowlists * Secrets: reapply gateway chat env allowlist * Secrets: reapply gateway chat env allowlist * Secrets: stabilize gateway chat env allowlist * Secrets: allowlist runtime snapshot save fixture * Secrets: allowlist oauth profile fixtures * Secrets: allowlist compaction identifier fixture * Secrets: allowlist model auth fixture * Secrets: allowlist model status fixtures * Secrets: allowlist custom onboarding fixture * Secrets: allowlist mattermost token summary fixtures * Secrets: allowlist gateway auth suite fixtures * Secrets: allowlist channel summary fixture * Secrets: allowlist provider usage auth fixtures * Secrets: allowlist media proxy fixture * Secrets: allowlist secrets audit fixtures * Secrets: refresh baseline after final fixture allowlists * Feishu: prefer explicit client timeout * Feishu: test direct timeout precedence
This commit is contained in:
@@ -7,10 +7,6 @@
|
||||
[exclude-files]
|
||||
# pnpm lockfiles contain lots of high-entropy package integrity blobs.
|
||||
pattern = (^|/)pnpm-lock\.yaml$
|
||||
# Generated output and vendored assets.
|
||||
pattern = (^|/)(dist|vendor)/
|
||||
# Local config file with allowlist patterns.
|
||||
pattern = (^|/)\.detect-secrets\.cfg$
|
||||
|
||||
[exclude-lines]
|
||||
# Fastlane checks for private key marker; not a real key.
|
||||
@@ -28,3 +24,5 @@ pattern = "talk\.apiKey"
|
||||
pattern = === "string"
|
||||
# specific optional-chaining password check that didn't match the line above.
|
||||
pattern = typeof remote\?\.password === "string"
|
||||
# Docker apt signing key fingerprint constant; not a secret.
|
||||
pattern = OPENCLAW_DOCKER_GPG_FINGERPRINT=
|
||||
|
||||
@@ -30,7 +30,7 @@ repos:
|
||||
- --baseline
|
||||
- .secrets.baseline
|
||||
- --exclude-files
|
||||
- '(^|/)(dist/|vendor/|pnpm-lock\.yaml$|\.detect-secrets\.cfg$)'
|
||||
- '(^|/)pnpm-lock\.yaml$'
|
||||
- --exclude-lines
|
||||
- 'key_content\.include\?\("BEGIN PRIVATE KEY"\)'
|
||||
- --exclude-lines
|
||||
@@ -47,6 +47,8 @@ repos:
|
||||
- '=== "string"'
|
||||
- --exclude-lines
|
||||
- 'typeof remote\?\.password === "string"'
|
||||
- --exclude-lines
|
||||
- "OPENCLAW_DOCKER_GPG_FINGERPRINT="
|
||||
# Shell script linting
|
||||
- repo: https://github.com/koalaman/shellcheck-precommit
|
||||
rev: v0.11.0
|
||||
|
||||
@@ -141,7 +141,8 @@
|
||||
"\"gateway\\.auth\\.password\"",
|
||||
"\"talk\\.apiKey\"",
|
||||
"=== \"string\"",
|
||||
"typeof remote\\?\\.password === \"string\""
|
||||
"typeof remote\\?\\.password === \"string\"",
|
||||
"OPENCLAW_DOCKER_GPG_FINGERPRINT="
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -152,14 +153,14 @@
|
||||
"filename": ".detect-secrets.cfg",
|
||||
"hashed_secret": "1348b145fa1a555461c1b790a2f66614781091e9",
|
||||
"is_verified": false,
|
||||
"line_number": 17
|
||||
"line_number": 13
|
||||
},
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": ".detect-secrets.cfg",
|
||||
"hashed_secret": "fe88fceb47e040ba1bfafa4ac639366188df2f6d",
|
||||
"is_verified": false,
|
||||
"line_number": 19
|
||||
"line_number": 15
|
||||
}
|
||||
],
|
||||
"appcast.xml": [
|
||||
@@ -12387,21 +12388,14 @@
|
||||
"filename": "src/config/schema.help.ts",
|
||||
"hashed_secret": "9f4cda226d3868676ac7f86f59e4190eb94bd208",
|
||||
"is_verified": false,
|
||||
"line_number": 109
|
||||
"line_number": 647
|
||||
},
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "src/config/schema.help.ts",
|
||||
"hashed_secret": "01822c8bbf6a8b136944b14182cb885100ec2eae",
|
||||
"is_verified": false,
|
||||
"line_number": 130
|
||||
},
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "src/config/schema.help.ts",
|
||||
"hashed_secret": "bb7dfd9746e660e4a4374951ec5938ef0e343255",
|
||||
"is_verified": false,
|
||||
"line_number": 187
|
||||
"line_number": 678
|
||||
}
|
||||
],
|
||||
"src/config/schema.irc.ts": [
|
||||
@@ -12720,21 +12714,21 @@
|
||||
"filename": "src/infra/provider-usage.auth.normalizes-keys.test.ts",
|
||||
"hashed_secret": "45c7365e3b542cdb4fae6ec10c2ff149224d7656",
|
||||
"is_verified": false,
|
||||
"line_number": 80
|
||||
"line_number": 123
|
||||
},
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "src/infra/provider-usage.auth.normalizes-keys.test.ts",
|
||||
"hashed_secret": "b67074884ab7ef7c7a8cd6a3da9565d96c792248",
|
||||
"is_verified": false,
|
||||
"line_number": 81
|
||||
"line_number": 124
|
||||
},
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "src/infra/provider-usage.auth.normalizes-keys.test.ts",
|
||||
"hashed_secret": "d4d8027e64f9cf4180d3aecfe31ea409368022ee",
|
||||
"is_verified": false,
|
||||
"line_number": 82
|
||||
"line_number": 125
|
||||
}
|
||||
],
|
||||
"src/infra/shell-env.test.ts": [
|
||||
@@ -12900,7 +12894,7 @@
|
||||
"filename": "src/media-understanding/runner.auto-audio.test.ts",
|
||||
"hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f",
|
||||
"is_verified": false,
|
||||
"line_number": 40
|
||||
"line_number": 23
|
||||
}
|
||||
],
|
||||
"src/media-understanding/runner.deepgram.test.ts": [
|
||||
@@ -12934,21 +12928,21 @@
|
||||
"filename": "src/memory/embeddings.test.ts",
|
||||
"hashed_secret": "a47110e348a3063541fb1f1f640d635d457181a0",
|
||||
"is_verified": false,
|
||||
"line_number": 45
|
||||
"line_number": 47
|
||||
},
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "src/memory/embeddings.test.ts",
|
||||
"hashed_secret": "c734e47630dda71619c696d88381f06f7511bd78",
|
||||
"is_verified": false,
|
||||
"line_number": 160
|
||||
"line_number": 195
|
||||
},
|
||||
{
|
||||
"type": "Secret Keyword",
|
||||
"filename": "src/memory/embeddings.test.ts",
|
||||
"hashed_secret": "56e1d57b8db262b08bc73c60ed08d8c92e59503f",
|
||||
"is_verified": false,
|
||||
"line_number": 189
|
||||
"line_number": 291
|
||||
}
|
||||
],
|
||||
"src/pairing/pairing-store.ts": [
|
||||
@@ -13060,7 +13054,7 @@
|
||||
"filename": "src/tui/gateway-chat.test.ts",
|
||||
"hashed_secret": "6255675480f681df08c1704b7b3cd2c49917f0e2",
|
||||
"is_verified": false,
|
||||
"line_number": 85
|
||||
"line_number": 60
|
||||
}
|
||||
],
|
||||
"src/web/login.test.ts": [
|
||||
@@ -13100,5 +13094,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"generated_at": "2026-02-17T13:34:38Z"
|
||||
"generated_at": "2026-03-07T00:11:03Z"
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@
|
||||
</ul>
|
||||
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
|
||||
]]></description>
|
||||
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.3.2/OpenClaw-2026.3.2.zip" length="23181513" type="application/octet-stream" sparkle:edSignature="THMgkcoMgz2vv5zse3Po3K7l3Or2RhBKurXZIi8iYVXN76yJy1YXAY6kXi6ovD+dbYn68JKYDIKA1Ya78bO7BQ=="/>
|
||||
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.3.2/OpenClaw-2026.3.2.zip" length="23181513" type="application/octet-stream" sparkle:edSignature="THMgkcoMgz2vv5zse3Po3K7l3Or2RhBKurXZIi8iYVXN76yJy1YXAY6kXi6ovD+dbYn68JKYDIKA1Ya78bO7BQ=="/> <!-- pragma: allowlist secret -->
|
||||
</item>
|
||||
<item>
|
||||
<title>2026.3.1</title>
|
||||
@@ -357,7 +357,7 @@
|
||||
</ul>
|
||||
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
|
||||
]]></description>
|
||||
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.3.1/OpenClaw-2026.3.1.zip" length="12804155" type="application/octet-stream" sparkle:edSignature="TF1otD4Vk3pG0iViX7mvix5DQEgAsk4JkSFvH7opjf9aawV16f29SUa2wRmiCFU6HEgyNgnGI/078O+A27eXCA=="/>
|
||||
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.3.1/OpenClaw-2026.3.1.zip" length="12804155" type="application/octet-stream" sparkle:edSignature="TF1otD4Vk3pG0iViX7mvix5DQEgAsk4JkSFvH7opjf9aawV16f29SUa2wRmiCFU6HEgyNgnGI/078O+A27eXCA=="/> <!-- pragma: allowlist secret -->
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
</rss>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package ai.openclaw.android.voice
|
||||
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.put
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertTrue
|
||||
@@ -38,16 +40,12 @@ class TalkModeConfigParsingTest {
|
||||
|
||||
@Test
|
||||
fun fallsBackToLegacyTalkFieldsWhenNormalizedPayloadMissing() {
|
||||
val legacyApiKey = "legacy-key" // pragma: allowlist secret
|
||||
val talk =
|
||||
json.parseToJsonElement(
|
||||
"""
|
||||
{
|
||||
"voiceId": "voice-legacy",
|
||||
"apiKey": "legacy-key"
|
||||
}
|
||||
""".trimIndent(),
|
||||
)
|
||||
.jsonObject
|
||||
buildJsonObject {
|
||||
put("voiceId", "voice-legacy")
|
||||
put("apiKey", legacyApiKey) // pragma: allowlist secret
|
||||
}
|
||||
|
||||
val selection = TalkModeManager.selectTalkProviderConfig(talk)
|
||||
assertNotNull(selection)
|
||||
|
||||
@@ -26,7 +26,7 @@ enum GatewaySettingsStore {
|
||||
private static let preferredGatewayStableIDAccount = "preferredStableID"
|
||||
private static let lastDiscoveredGatewayStableIDAccount = "lastDiscoveredStableID"
|
||||
private static let lastGatewayConnectionAccount = "lastConnection"
|
||||
private static let talkProviderApiKeyAccountPrefix = "provider.apiKey."
|
||||
private static let talkProviderApiKeyAccountPrefix = "provider.apiKey." // pragma: allowlist secret
|
||||
|
||||
static func bootstrapPersistence() {
|
||||
self.ensureStableInstanceID()
|
||||
|
||||
@@ -23,7 +23,7 @@ import Testing
|
||||
@Test func ignoresLegacyTalkFieldsWhenNormalizedPayloadMissing() {
|
||||
let talk: [String: Any] = [
|
||||
"voiceId": "voice-legacy",
|
||||
"apiKey": "legacy-key",
|
||||
"apiKey": "legacy-key", // pragma: allowlist secret
|
||||
]
|
||||
|
||||
let selection = TalkModeManager.selectTalkProviderConfig(talk)
|
||||
|
||||
@@ -804,7 +804,7 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \
|
||||
```yaml
|
||||
channels:
|
||||
telegram:
|
||||
proxy: socks5://user:pass@proxy-host:1080
|
||||
proxy: socks5://<user>:<password>@proxy-host:1080
|
||||
```
|
||||
|
||||
- Node 22+ defaults to `autoSelectFamily=true` (except WSL2) and `dnsResultOrder=ipv4first`.
|
||||
|
||||
@@ -179,8 +179,8 @@ Request payload (stdin):
|
||||
|
||||
Response payload (stdout):
|
||||
|
||||
```json
|
||||
{ "protocolVersion": 1, "values": { "providers/openai/apiKey": "sk-..." } }
|
||||
```jsonc
|
||||
{ "protocolVersion": 1, "values": { "providers/openai/apiKey": "<openai-api-key>" } } // pragma: allowlist secret
|
||||
```
|
||||
|
||||
Optional per-id errors:
|
||||
|
||||
@@ -197,7 +197,7 @@ See [Pi USB boot guide](https://www.raspberrypi.com/documentation/computers/rasp
|
||||
On lower-power Pi hosts, enable Node's module compile cache so repeated CLI runs are faster:
|
||||
|
||||
```bash
|
||||
grep -q 'NODE_COMPILE_CACHE=/var/tmp/openclaw-compile-cache' ~/.bashrc || cat >> ~/.bashrc <<'EOF'
|
||||
grep -q 'NODE_COMPILE_CACHE=/var/tmp/openclaw-compile-cache' ~/.bashrc || cat >> ~/.bashrc <<'EOF' # pragma: allowlist secret
|
||||
export NODE_COMPILE_CACHE=/var/tmp/openclaw-compile-cache
|
||||
mkdir -p /var/tmp/openclaw-compile-cache
|
||||
export OPENCLAW_NO_RESPAWN=1
|
||||
|
||||
@@ -25,14 +25,14 @@ openclaw onboard --kilocode-api-key <key>
|
||||
Or set the environment variable:
|
||||
|
||||
```bash
|
||||
export KILOCODE_API_KEY="your-api-key"
|
||||
export KILOCODE_API_KEY="<your-kilocode-api-key>" # pragma: allowlist secret
|
||||
```
|
||||
|
||||
## Config snippet
|
||||
|
||||
```json5
|
||||
{
|
||||
env: { KILOCODE_API_KEY: "sk-..." },
|
||||
env: { KILOCODE_API_KEY: "<your-kilocode-api-key>" }, // pragma: allowlist secret
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "kilocode/anthropic/claude-opus-4.6" },
|
||||
|
||||
@@ -5,7 +5,7 @@ describe("BlueBubblesConfigSchema", () => {
|
||||
it("accepts account config when serverUrl and password are both set", () => {
|
||||
const parsed = BlueBubblesConfigSchema.safeParse({
|
||||
serverUrl: "http://localhost:1234",
|
||||
password: "secret",
|
||||
password: "secret", // pragma: allowlist secret
|
||||
});
|
||||
expect(parsed.success).toBe(true);
|
||||
});
|
||||
|
||||
@@ -192,7 +192,7 @@ describe("createFeishuClient HTTP timeout", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("uses env timeout override when provided", async () => {
|
||||
it("uses env timeout override when provided and no direct timeout is set", async () => {
|
||||
process.env[FEISHU_HTTP_TIMEOUT_ENV_VAR] = "60000";
|
||||
|
||||
createFeishuClient({
|
||||
@@ -214,6 +214,29 @@ describe("createFeishuClient HTTP timeout", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("prefers direct timeout over env override", async () => {
|
||||
process.env[FEISHU_HTTP_TIMEOUT_ENV_VAR] = "60000";
|
||||
|
||||
createFeishuClient({
|
||||
appId: "app_10",
|
||||
appSecret: "secret_10",
|
||||
accountId: "timeout-direct-override",
|
||||
httpTimeoutMs: 120_000,
|
||||
config: { httpTimeoutMs: 45_000 },
|
||||
});
|
||||
|
||||
const calls = (LarkClient as unknown as ReturnType<typeof vi.fn>).mock.calls;
|
||||
const lastCall = calls[calls.length - 1][0] as {
|
||||
httpInstance: { get: (...args: unknown[]) => Promise<unknown> };
|
||||
};
|
||||
await lastCall.httpInstance.get("https://example.com/api");
|
||||
|
||||
expect(mockBaseHttpInstance.get).toHaveBeenCalledWith(
|
||||
"https://example.com/api",
|
||||
expect.objectContaining({ timeout: 120_000 }),
|
||||
);
|
||||
});
|
||||
|
||||
it("clamps env timeout override to max bound", async () => {
|
||||
process.env[FEISHU_HTTP_TIMEOUT_ENV_VAR] = String(FEISHU_HTTP_TIMEOUT_MAX_MS + 123_456);
|
||||
|
||||
|
||||
@@ -79,6 +79,15 @@ function resolveConfiguredHttpTimeoutMs(creds: FeishuClientCredentials): number
|
||||
return Math.min(Math.max(rounded, 1), FEISHU_HTTP_TIMEOUT_MAX_MS);
|
||||
};
|
||||
|
||||
const fromDirectField = creds.httpTimeoutMs;
|
||||
if (
|
||||
typeof fromDirectField === "number" &&
|
||||
Number.isFinite(fromDirectField) &&
|
||||
fromDirectField > 0
|
||||
) {
|
||||
return clampTimeout(fromDirectField);
|
||||
}
|
||||
|
||||
const envRaw = process.env[FEISHU_HTTP_TIMEOUT_ENV_VAR];
|
||||
if (envRaw) {
|
||||
const envValue = Number(envRaw);
|
||||
@@ -88,8 +97,7 @@ function resolveConfiguredHttpTimeoutMs(creds: FeishuClientCredentials): number
|
||||
}
|
||||
|
||||
const fromConfig = creds.config?.httpTimeoutMs;
|
||||
const fromDirectField = creds.httpTimeoutMs;
|
||||
const timeout = fromDirectField ?? fromConfig;
|
||||
const timeout = fromConfig;
|
||||
if (typeof timeout !== "number" || !Number.isFinite(timeout) || timeout <= 0) {
|
||||
return FEISHU_HTTP_TIMEOUT_MS;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ function buildDebounceAccount(): ResolvedFeishuAccount {
|
||||
enabled: true,
|
||||
configured: true,
|
||||
appId: "cli_test",
|
||||
appSecret: "secret_test",
|
||||
appSecret: "secret_test", // pragma: allowlist secret
|
||||
domain: "feishu",
|
||||
config: {
|
||||
enabled: true,
|
||||
|
||||
@@ -41,7 +41,7 @@ function buildMultiAccountWebsocketConfig(accountIds: string[]): ClawdbotConfig
|
||||
{
|
||||
enabled: true,
|
||||
appId: `cli_${accountId}`,
|
||||
appSecret: `secret_${accountId}`,
|
||||
appSecret: `secret_${accountId}`, // pragma: allowlist secret
|
||||
connectionMode: "websocket",
|
||||
},
|
||||
]),
|
||||
|
||||
@@ -45,7 +45,7 @@ describe("nextcloud-talk inbound authz", () => {
|
||||
enabled: true,
|
||||
baseUrl: "",
|
||||
secret: "",
|
||||
secretSource: "none",
|
||||
secretSource: "none", // pragma: allowlist secret
|
||||
config: {
|
||||
dmPolicy: "pairing",
|
||||
allowFrom: [],
|
||||
|
||||
@@ -16,7 +16,7 @@ export function createSignedCreateMessageRequest(params?: { backend?: string })
|
||||
const body = JSON.stringify(payload);
|
||||
const { random, signature } = generateNextcloudTalkSignature({
|
||||
body,
|
||||
secret: "nextcloud-secret",
|
||||
secret: "nextcloud-secret", // pragma: allowlist secret
|
||||
});
|
||||
return {
|
||||
body,
|
||||
|
||||
@@ -130,7 +130,7 @@ describe("ensureAuthProfileStore", () => {
|
||||
profile: {
|
||||
provider: "anthropic",
|
||||
mode: "api_key",
|
||||
apiKey: "sk-ant-alias",
|
||||
apiKey: "sk-ant-alias", // pragma: allowlist secret
|
||||
},
|
||||
expected: {
|
||||
type: "api_key",
|
||||
@@ -156,7 +156,7 @@ describe("ensureAuthProfileStore", () => {
|
||||
provider: "anthropic",
|
||||
type: "api_key",
|
||||
key: "sk-ant-canonical",
|
||||
apiKey: "sk-ant-alias",
|
||||
apiKey: "sk-ant-alias", // pragma: allowlist secret
|
||||
},
|
||||
expected: {
|
||||
type: "api_key",
|
||||
@@ -210,7 +210,7 @@ describe("ensureAuthProfileStore", () => {
|
||||
anthropic: {
|
||||
provider: "anthropic",
|
||||
mode: "api_key",
|
||||
apiKey: "sk-ant-legacy",
|
||||
apiKey: "sk-ant-legacy", // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
null,
|
||||
|
||||
@@ -37,7 +37,7 @@ describe("auth profile runtime snapshot persistence", () => {
|
||||
|
||||
const snapshot = await prepareSecretsRuntimeSnapshot({
|
||||
config: {},
|
||||
env: { OPENAI_API_KEY: "sk-runtime-openai" },
|
||||
env: { OPENAI_API_KEY: "sk-runtime-openai" }, // pragma: allowlist secret
|
||||
agentDirs: [agentDir],
|
||||
});
|
||||
activateSecretsRuntimeSnapshot(snapshot);
|
||||
|
||||
@@ -65,7 +65,7 @@ describe("resolveApiKeyForProfile config compatibility", () => {
|
||||
profileId,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
apiKey: "tok-123",
|
||||
apiKey: "tok-123", // pragma: allowlist secret
|
||||
provider: "anthropic",
|
||||
email: undefined,
|
||||
});
|
||||
@@ -124,7 +124,7 @@ describe("resolveApiKeyForProfile config compatibility", () => {
|
||||
});
|
||||
// token ↔ oauth are bidirectionally compatible bearer-token auth paths.
|
||||
expect(result).toEqual({
|
||||
apiKey: "access-123",
|
||||
apiKey: "access-123", // pragma: allowlist secret
|
||||
provider: "anthropic",
|
||||
email: undefined,
|
||||
});
|
||||
@@ -145,7 +145,7 @@ describe("resolveApiKeyForProfile token expiry handling", () => {
|
||||
}),
|
||||
});
|
||||
expect(result).toEqual({
|
||||
apiKey: "tok-123",
|
||||
apiKey: "tok-123", // pragma: allowlist secret
|
||||
provider: "anthropic",
|
||||
email: undefined,
|
||||
});
|
||||
@@ -165,7 +165,7 @@ describe("resolveApiKeyForProfile token expiry handling", () => {
|
||||
}),
|
||||
});
|
||||
expect(result).toEqual({
|
||||
apiKey: "tok-123",
|
||||
apiKey: "tok-123", // pragma: allowlist secret
|
||||
provider: "anthropic",
|
||||
email: undefined,
|
||||
});
|
||||
@@ -231,7 +231,7 @@ describe("resolveApiKeyForProfile secret refs", () => {
|
||||
it("resolves api_key keyRef from env", async () => {
|
||||
const profileId = "openai:default";
|
||||
const previous = process.env.OPENAI_API_KEY;
|
||||
process.env.OPENAI_API_KEY = "sk-openai-ref";
|
||||
process.env.OPENAI_API_KEY = "sk-openai-ref"; // pragma: allowlist secret
|
||||
try {
|
||||
const result = await resolveApiKeyForProfile({
|
||||
cfg: cfgFor(profileId, "openai", "api_key"),
|
||||
@@ -248,7 +248,7 @@ describe("resolveApiKeyForProfile secret refs", () => {
|
||||
profileId,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
apiKey: "sk-openai-ref",
|
||||
apiKey: "sk-openai-ref", // pragma: allowlist secret
|
||||
provider: "openai",
|
||||
email: undefined,
|
||||
});
|
||||
@@ -282,7 +282,7 @@ describe("resolveApiKeyForProfile secret refs", () => {
|
||||
profileId,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
apiKey: "gh-ref-token",
|
||||
apiKey: "gh-ref-token", // pragma: allowlist secret
|
||||
provider: "github-copilot",
|
||||
email: undefined,
|
||||
});
|
||||
@@ -315,7 +315,7 @@ describe("resolveApiKeyForProfile secret refs", () => {
|
||||
profileId,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
apiKey: "gh-ref-token",
|
||||
apiKey: "gh-ref-token", // pragma: allowlist secret
|
||||
provider: "github-copilot",
|
||||
email: undefined,
|
||||
});
|
||||
@@ -331,7 +331,7 @@ describe("resolveApiKeyForProfile secret refs", () => {
|
||||
it("resolves inline ${ENV} api_key values", async () => {
|
||||
const profileId = "openai:inline-env";
|
||||
const previous = process.env.OPENAI_API_KEY;
|
||||
process.env.OPENAI_API_KEY = "sk-openai-inline";
|
||||
process.env.OPENAI_API_KEY = "sk-openai-inline"; // pragma: allowlist secret
|
||||
try {
|
||||
const result = await resolveApiKeyForProfile({
|
||||
cfg: cfgFor(profileId, "openai", "api_key"),
|
||||
@@ -348,7 +348,7 @@ describe("resolveApiKeyForProfile secret refs", () => {
|
||||
profileId,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
apiKey: "sk-openai-inline",
|
||||
apiKey: "sk-openai-inline", // pragma: allowlist secret
|
||||
provider: "openai",
|
||||
email: undefined,
|
||||
});
|
||||
@@ -381,7 +381,7 @@ describe("resolveApiKeyForProfile secret refs", () => {
|
||||
profileId,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
apiKey: "gh-inline-token",
|
||||
apiKey: "gh-inline-token", // pragma: allowlist secret
|
||||
provider: "github-copilot",
|
||||
email: undefined,
|
||||
});
|
||||
|
||||
@@ -31,7 +31,7 @@ describe("compaction identifier-preservation instructions", () => {
|
||||
} as unknown as NonNullable<ExtensionContext["model"]>;
|
||||
const summarizeBase: Omit<SummarizeInStagesInput, "messages"> = {
|
||||
model: testModel,
|
||||
apiKey: "test-key",
|
||||
apiKey: "test-key", // pragma: allowlist secret
|
||||
reserveTokens: 4000,
|
||||
maxChunkTokens: 8000,
|
||||
contextWindow: 200_000,
|
||||
|
||||
@@ -7,7 +7,7 @@ describe("resolveAwsSdkEnvVarName", () => {
|
||||
const env = {
|
||||
AWS_BEARER_TOKEN_BEDROCK: "bearer",
|
||||
AWS_ACCESS_KEY_ID: "access",
|
||||
AWS_SECRET_ACCESS_KEY: "secret",
|
||||
AWS_SECRET_ACCESS_KEY: "secret", // pragma: allowlist secret
|
||||
AWS_PROFILE: "default",
|
||||
} as NodeJS.ProcessEnv;
|
||||
|
||||
@@ -17,7 +17,7 @@ describe("resolveAwsSdkEnvVarName", () => {
|
||||
it("uses access keys when bearer token is missing", () => {
|
||||
const env = {
|
||||
AWS_ACCESS_KEY_ID: "access",
|
||||
AWS_SECRET_ACCESS_KEY: "secret",
|
||||
AWS_SECRET_ACCESS_KEY: "secret", // pragma: allowlist secret
|
||||
AWS_PROFILE: "default",
|
||||
} as NodeJS.ProcessEnv;
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ function resolveSyntheticLocalProviderAuth(params: {
|
||||
}
|
||||
|
||||
return {
|
||||
apiKey: "ollama-local",
|
||||
apiKey: "ollama-local", // pragma: allowlist secret
|
||||
source: "models.providers.ollama (synthetic local key)",
|
||||
mode: "api-key",
|
||||
};
|
||||
|
||||
@@ -119,9 +119,10 @@ function createAuthStorage(AuthStorageLike: unknown, path: string, creds: PiCred
|
||||
? withFactory.create(path)
|
||||
: new (AuthStorageLike as { new (path: string): unknown })(path)
|
||||
) as PiAuthStorage & {
|
||||
setRuntimeApiKey?: (provider: string, apiKey: string) => void;
|
||||
setRuntimeApiKey?: (provider: string, apiKey: string) => void; // pragma: allowlist secret
|
||||
};
|
||||
if (typeof withRuntimeOverride.setRuntimeApiKey === "function") {
|
||||
const hasRuntimeApiKeyOverride = typeof withRuntimeOverride.setRuntimeApiKey === "function"; // pragma: allowlist secret
|
||||
if (hasRuntimeApiKeyOverride) {
|
||||
for (const [provider, credential] of Object.entries(creds)) {
|
||||
if (credential.type === "api_key") {
|
||||
withRuntimeOverride.setRuntimeApiKey(provider, credential.key);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import crypto from "node:crypto";
|
||||
|
||||
export const NOVNC_PASSWORD_ENV_KEY = "OPENCLAW_BROWSER_NOVNC_PASSWORD";
|
||||
export const NOVNC_PASSWORD_ENV_KEY = "OPENCLAW_BROWSER_NOVNC_PASSWORD"; // pragma: allowlist secret
|
||||
const NOVNC_TOKEN_TTL_MS = 60 * 1000;
|
||||
const NOVNC_PASSWORD_LENGTH = 8;
|
||||
const NOVNC_PASSWORD_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
@@ -25,7 +25,7 @@ type ResolveCommandSecretsResult = {
|
||||
hadUnresolvedTargets: boolean;
|
||||
};
|
||||
|
||||
export type CommandSecretResolutionMode = "strict" | "summary" | "operational_readonly";
|
||||
export type CommandSecretResolutionMode = "strict" | "summary" | "operational_readonly"; // pragma: allowlist secret
|
||||
|
||||
export type CommandSecretTargetState =
|
||||
| "resolved_gateway"
|
||||
|
||||
@@ -20,7 +20,7 @@ import type { SecretInputMode } from "./onboard-types.js";
|
||||
|
||||
const ENV_SOURCE_LABEL_RE = /(?:^|:\s)([A-Z][A-Z0-9_]*)$/;
|
||||
|
||||
type SecretRefChoice = "env" | "provider";
|
||||
type SecretRefChoice = "env" | "provider"; // pragma: allowlist secret
|
||||
|
||||
export type SecretInputModePromptCopy = {
|
||||
modeMessage?: string;
|
||||
@@ -101,7 +101,7 @@ export async function promptSecretRefForOnboarding(params: {
|
||||
const defaultEnvVar =
|
||||
params.preferredEnvVar ?? resolveDefaultProviderEnvVar(params.provider) ?? "";
|
||||
const defaultFilePointer = resolveDefaultFilePointerId(params.provider);
|
||||
let sourceChoice: SecretRefChoice = "env";
|
||||
let sourceChoice: SecretRefChoice = "env"; // pragma: allowlist secret
|
||||
|
||||
while (true) {
|
||||
const sourceRaw: SecretRefChoice = await params.prompter.select<SecretRefChoice>({
|
||||
|
||||
@@ -9,14 +9,14 @@ const mocks = vi.hoisted(() => {
|
||||
type: "oauth",
|
||||
provider: "anthropic",
|
||||
access: "sk-ant-oat01-ACCESS-TOKEN-1234567890",
|
||||
refresh: "sk-ant-ort01-REFRESH-TOKEN-1234567890",
|
||||
refresh: "sk-ant-ort01-REFRESH-TOKEN-1234567890", // pragma: allowlist secret
|
||||
expires: Date.now() + 60_000,
|
||||
email: "peter@example.com",
|
||||
},
|
||||
"anthropic:work": {
|
||||
type: "api_key",
|
||||
provider: "anthropic",
|
||||
key: "sk-ant-api-0123456789abcdefghijklmnopqrstuvwxyz",
|
||||
key: "sk-ant-api-0123456789abcdefghijklmnopqrstuvwxyz", // pragma: allowlist secret
|
||||
},
|
||||
"openai-codex:default": {
|
||||
type: "oauth",
|
||||
@@ -49,13 +49,13 @@ const mocks = vi.hoisted(() => {
|
||||
resolveEnvApiKey: vi.fn((provider: string) => {
|
||||
if (provider === "openai") {
|
||||
return {
|
||||
apiKey: "sk-openai-0123456789abcdefghijklmnopqrstuvwxyz",
|
||||
apiKey: "sk-openai-0123456789abcdefghijklmnopqrstuvwxyz", // pragma: allowlist secret
|
||||
source: "shell env: OPENAI_API_KEY",
|
||||
};
|
||||
}
|
||||
if (provider === "anthropic") {
|
||||
return {
|
||||
apiKey: "sk-ant-oat01-ACCESS-TOKEN-1234567890",
|
||||
apiKey: "sk-ant-oat01-ACCESS-TOKEN-1234567890", // pragma: allowlist secret
|
||||
source: "env: ANTHROPIC_OAUTH_TOKEN",
|
||||
};
|
||||
}
|
||||
@@ -231,7 +231,7 @@ describe("modelsStatusCommand auth overview", () => {
|
||||
|
||||
it("does not emit raw short api-key values in JSON labels", async () => {
|
||||
const localRuntime = createRuntime();
|
||||
const shortSecret = "abc123";
|
||||
const shortSecret = "abc123"; // pragma: allowlist secret
|
||||
const originalProfiles = { ...mocks.store.profiles };
|
||||
mocks.store.profiles = {
|
||||
...mocks.store.profiles,
|
||||
|
||||
@@ -63,7 +63,8 @@ function resolveApiKeySecretInput(
|
||||
if (inlineEnvRef) {
|
||||
return inlineEnvRef;
|
||||
}
|
||||
if (options?.secretInputMode === "ref") {
|
||||
const useSecretRefMode = options?.secretInputMode === "ref"; // pragma: allowlist secret
|
||||
if (useSecretRefMode) {
|
||||
return resolveProviderDefaultEnvSecretRef(provider);
|
||||
}
|
||||
return normalized;
|
||||
|
||||
@@ -429,7 +429,7 @@ describe("parseNonInteractiveCustomApiFlags", () => {
|
||||
baseUrl: "https://llm.example.com/v1",
|
||||
modelId: "foo-large",
|
||||
compatibility: "openai",
|
||||
apiKey: "custom-test-key",
|
||||
apiKey: "custom-test-key", // pragma: allowlist secret
|
||||
providerId: "my-custom",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -184,7 +184,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
await withOnboardEnv("openclaw-onboard-minimax-", async (env) => {
|
||||
const cfg = await runOnboardingAndReadConfig(env, {
|
||||
authChoice: "minimax-api",
|
||||
minimaxApiKey: "sk-minimax-test",
|
||||
minimaxApiKey: "sk-minimax-test", // pragma: allowlist secret
|
||||
});
|
||||
|
||||
expect(cfg.auth?.profiles?.["minimax:default"]?.provider).toBe("minimax");
|
||||
@@ -203,7 +203,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
await withOnboardEnv("openclaw-onboard-minimax-cn-", async (env) => {
|
||||
const cfg = await runOnboardingAndReadConfig(env, {
|
||||
authChoice: "minimax-api-key-cn",
|
||||
minimaxApiKey: "sk-minimax-test",
|
||||
minimaxApiKey: "sk-minimax-test", // pragma: allowlist secret
|
||||
});
|
||||
|
||||
expect(cfg.auth?.profiles?.["minimax-cn:default"]?.provider).toBe("minimax-cn");
|
||||
@@ -222,7 +222,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
await withOnboardEnv("openclaw-onboard-zai-", async (env) => {
|
||||
const cfg = await runOnboardingAndReadConfig(env, {
|
||||
authChoice: "zai-api-key",
|
||||
zaiApiKey: "zai-test-key",
|
||||
zaiApiKey: "zai-test-key", // pragma: allowlist secret
|
||||
});
|
||||
|
||||
expect(cfg.auth?.profiles?.["zai:default"]?.provider).toBe("zai");
|
||||
@@ -237,7 +237,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
await withOnboardEnv("openclaw-onboard-zai-cn-", async (env) => {
|
||||
const cfg = await runOnboardingAndReadConfig(env, {
|
||||
authChoice: "zai-coding-cn",
|
||||
zaiApiKey: "zai-test-key",
|
||||
zaiApiKey: "zai-test-key", // pragma: allowlist secret
|
||||
});
|
||||
|
||||
expect(cfg.models?.providers?.zai?.baseUrl).toBe(
|
||||
@@ -264,7 +264,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
it("infers Mistral auth choice from --mistral-api-key and sets default model", async () => {
|
||||
await withOnboardEnv("openclaw-onboard-mistral-infer-", async (env) => {
|
||||
const cfg = await runOnboardingAndReadConfig(env, {
|
||||
mistralApiKey: "mistral-test-key",
|
||||
mistralApiKey: "mistral-test-key", // pragma: allowlist secret
|
||||
});
|
||||
|
||||
expect(cfg.auth?.profiles?.["mistral:default"]?.provider).toBe("mistral");
|
||||
@@ -282,7 +282,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
await withOnboardEnv("openclaw-onboard-volcengine-", async (env) => {
|
||||
const cfg = await runOnboardingAndReadConfig(env, {
|
||||
authChoice: "volcengine-api-key",
|
||||
volcengineApiKey: "volcengine-test-key",
|
||||
volcengineApiKey: "volcengine-test-key", // pragma: allowlist secret
|
||||
});
|
||||
|
||||
expect(cfg.agents?.defaults?.model?.primary).toBe("volcengine-plan/ark-code-latest");
|
||||
@@ -292,7 +292,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
it("infers BytePlus auth choice from --byteplus-api-key and sets default model", async () => {
|
||||
await withOnboardEnv("openclaw-onboard-byteplus-infer-", async (env) => {
|
||||
const cfg = await runOnboardingAndReadConfig(env, {
|
||||
byteplusApiKey: "byteplus-test-key",
|
||||
byteplusApiKey: "byteplus-test-key", // pragma: allowlist secret
|
||||
});
|
||||
|
||||
expect(cfg.agents?.defaults?.model?.primary).toBe("byteplus-plan/ark-code-latest");
|
||||
@@ -303,7 +303,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
await withOnboardEnv("openclaw-onboard-ai-gateway-", async (env) => {
|
||||
const cfg = await runOnboardingAndReadConfig(env, {
|
||||
authChoice: "ai-gateway-api-key",
|
||||
aiGatewayApiKey: "gateway-test-key",
|
||||
aiGatewayApiKey: "gateway-test-key", // pragma: allowlist secret
|
||||
});
|
||||
|
||||
expect(cfg.auth?.profiles?.["vercel-ai-gateway:default"]?.provider).toBe("vercel-ai-gateway");
|
||||
@@ -350,7 +350,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
await withOnboardEnv("openclaw-onboard-openai-", async (env) => {
|
||||
const cfg = await runOnboardingAndReadConfig(env, {
|
||||
authChoice: "openai-api-key",
|
||||
openaiApiKey: "sk-openai-test",
|
||||
openaiApiKey: "sk-openai-test", // pragma: allowlist secret
|
||||
});
|
||||
|
||||
expect(cfg.agents?.defaults?.model?.primary).toBe(OPENAI_DEFAULT_MODEL);
|
||||
@@ -410,10 +410,10 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
"fails fast for $name when --secret-input-mode ref uses explicit key without env and does not leak the key",
|
||||
async ({ prefix, authChoice, optionKey, flagName, envVar }) => {
|
||||
await withOnboardEnv(prefix, async ({ runtime }) => {
|
||||
const providedSecret = `${envVar.toLowerCase()}-should-not-leak`;
|
||||
const providedSecret = `${envVar.toLowerCase()}-should-not-leak`; // pragma: allowlist secret
|
||||
const options: Record<string, unknown> = {
|
||||
authChoice,
|
||||
secretInputMode: "ref",
|
||||
secretInputMode: "ref", // pragma: allowlist secret
|
||||
[optionKey]: providedSecret,
|
||||
skipSkills: true,
|
||||
};
|
||||
@@ -447,12 +447,12 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
await withEnvAsync(
|
||||
{
|
||||
OPENCODE_API_KEY: undefined,
|
||||
OPENCODE_ZEN_API_KEY: "opencode-zen-env-key",
|
||||
OPENCODE_ZEN_API_KEY: "opencode-zen-env-key", // pragma: allowlist secret
|
||||
},
|
||||
async () => {
|
||||
await runNonInteractiveOnboardingWithDefaults(runtime, {
|
||||
authChoice: "opencode-zen",
|
||||
secretInputMode: "ref",
|
||||
secretInputMode: "ref", // pragma: allowlist secret
|
||||
skipSkills: true,
|
||||
});
|
||||
|
||||
@@ -487,7 +487,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
await withOnboardEnv("openclaw-onboard-litellm-", async (env) => {
|
||||
const cfg = await runOnboardingAndReadConfig(env, {
|
||||
authChoice: "litellm-api-key",
|
||||
litellmApiKey: "litellm-test-key",
|
||||
litellmApiKey: "litellm-test-key", // pragma: allowlist secret
|
||||
});
|
||||
|
||||
expect(cfg.auth?.profiles?.["litellm:default"]?.provider).toBe("litellm");
|
||||
@@ -519,7 +519,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
await runNonInteractiveOnboardingWithDefaults(runtime, {
|
||||
cloudflareAiGatewayAccountId: "cf-account-id",
|
||||
cloudflareAiGatewayGatewayId: "cf-gateway-id",
|
||||
cloudflareAiGatewayApiKey: "cf-gateway-test-key",
|
||||
cloudflareAiGatewayApiKey: "cf-gateway-test-key", // pragma: allowlist secret
|
||||
skipSkills: true,
|
||||
...options,
|
||||
});
|
||||
@@ -543,7 +543,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
it("infers Together auth choice from --together-api-key and sets default model", async () => {
|
||||
await withOnboardEnv("openclaw-onboard-together-infer-", async (env) => {
|
||||
const cfg = await runOnboardingAndReadConfig(env, {
|
||||
togetherApiKey: "together-test-key",
|
||||
togetherApiKey: "together-test-key", // pragma: allowlist secret
|
||||
});
|
||||
|
||||
expect(cfg.auth?.profiles?.["together:default"]?.provider).toBe("together");
|
||||
@@ -560,7 +560,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
it("infers QIANFAN auth choice from --qianfan-api-key and sets default model", async () => {
|
||||
await withOnboardEnv("openclaw-onboard-qianfan-infer-", async (env) => {
|
||||
const cfg = await runOnboardingAndReadConfig(env, {
|
||||
qianfanApiKey: "qianfan-test-key",
|
||||
qianfanApiKey: "qianfan-test-key", // pragma: allowlist secret
|
||||
});
|
||||
|
||||
expect(cfg.auth?.profiles?.["qianfan:default"]?.provider).toBe("qianfan");
|
||||
@@ -579,7 +579,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
await runNonInteractiveOnboardingWithDefaults(runtime, {
|
||||
authChoice: "custom-api-key",
|
||||
customBaseUrl: "https://llm.example.com/v1",
|
||||
customApiKey: "custom-test-key",
|
||||
customApiKey: "custom-test-key", // pragma: allowlist secret
|
||||
customModelId: "foo-large",
|
||||
customCompatibility: "anthropic",
|
||||
skipSkills: true,
|
||||
@@ -603,7 +603,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
await runNonInteractiveOnboardingWithDefaults(runtime, {
|
||||
customBaseUrl: "https://models.custom.local/v1",
|
||||
customModelId: "local-large",
|
||||
customApiKey: "custom-test-key",
|
||||
customApiKey: "custom-test-key", // pragma: allowlist secret
|
||||
skipSkills: true,
|
||||
});
|
||||
|
||||
@@ -624,7 +624,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
await withOnboardEnv(
|
||||
"openclaw-onboard-custom-provider-env-fallback-",
|
||||
async ({ configPath, runtime }) => {
|
||||
process.env.CUSTOM_API_KEY = "custom-env-key";
|
||||
process.env.CUSTOM_API_KEY = "custom-env-key"; // pragma: allowlist secret
|
||||
await runCustomLocalNonInteractive(runtime);
|
||||
expect(await readCustomLocalProviderApiKey(configPath)).toBe("custom-env-key");
|
||||
},
|
||||
@@ -635,9 +635,9 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
await withOnboardEnv(
|
||||
"openclaw-onboard-custom-provider-env-ref-",
|
||||
async ({ configPath, runtime }) => {
|
||||
process.env.CUSTOM_API_KEY = "custom-env-key";
|
||||
process.env.CUSTOM_API_KEY = "custom-env-key"; // pragma: allowlist secret
|
||||
await runCustomLocalNonInteractive(runtime, {
|
||||
secretInputMode: "ref",
|
||||
secretInputMode: "ref", // pragma: allowlist secret
|
||||
});
|
||||
expect(await readCustomLocalProviderApiKeyInput(configPath)).toEqual({
|
||||
source: "env",
|
||||
@@ -650,12 +650,12 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
|
||||
it("fails fast for custom provider ref mode when --custom-api-key is set but CUSTOM_API_KEY env is missing", async () => {
|
||||
await withOnboardEnv("openclaw-onboard-custom-provider-ref-flag-", async ({ runtime }) => {
|
||||
const providedSecret = "custom-inline-key-should-not-leak";
|
||||
const providedSecret = "custom-inline-key-should-not-leak"; // pragma: allowlist secret
|
||||
await withEnvAsync({ CUSTOM_API_KEY: undefined }, async () => {
|
||||
let thrown: Error | undefined;
|
||||
try {
|
||||
await runCustomLocalNonInteractive(runtime, {
|
||||
secretInputMode: "ref",
|
||||
secretInputMode: "ref", // pragma: allowlist secret
|
||||
customApiKey: providedSecret,
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -731,7 +731,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
async ({ runtime }) => {
|
||||
await expect(
|
||||
runNonInteractiveOnboardingWithDefaults(runtime, {
|
||||
customApiKey: "custom-test-key",
|
||||
customApiKey: "custom-test-key", // pragma: allowlist secret
|
||||
skipSkills: true,
|
||||
}),
|
||||
).rejects.toThrow('Auth choice "custom-api-key" requires a base URL and model ID.');
|
||||
|
||||
@@ -70,7 +70,8 @@ export async function resolveNonInteractiveApiKey(params: {
|
||||
const resolvedEnvKey = envResolved?.apiKey ?? explicitEnvKey;
|
||||
const resolvedEnvVarName = parseEnvVarNameFromSourceLabel(envResolved?.source) ?? explicitEnvVar;
|
||||
|
||||
if (params.secretInputMode === "ref") {
|
||||
const useSecretRefMode = params.secretInputMode === "ref"; // pragma: allowlist secret
|
||||
if (useSecretRefMode) {
|
||||
if (!resolvedEnvKey && flagKey) {
|
||||
params.runtime.error(
|
||||
[
|
||||
|
||||
@@ -91,7 +91,8 @@ export async function applyNonInteractiveAuthChoice(params: {
|
||||
? { secretInputMode: requestedSecretInputMode }
|
||||
: undefined;
|
||||
const toStoredSecretInput = (resolved: ResolvedNonInteractiveApiKey): SecretInput | null => {
|
||||
if (requestedSecretInputMode !== "ref") {
|
||||
const storePlaintextSecret = requestedSecretInputMode !== "ref"; // pragma: allowlist secret
|
||||
if (storePlaintextSecret) {
|
||||
return resolved.key;
|
||||
}
|
||||
if (resolved.source !== "env") {
|
||||
@@ -948,7 +949,8 @@ export async function applyNonInteractiveAuthChoice(params: {
|
||||
});
|
||||
let customApiKeyInput: SecretInput | undefined;
|
||||
if (resolvedCustomApiKey) {
|
||||
if (requestedSecretInputMode === "ref") {
|
||||
const storeCustomApiKeyAsRef = requestedSecretInputMode === "ref"; // pragma: allowlist secret
|
||||
if (storeCustomApiKeyAsRef) {
|
||||
const stored = toStoredSecretInput(resolvedCustomApiKey);
|
||||
if (!stored) {
|
||||
return null;
|
||||
|
||||
@@ -121,7 +121,7 @@ describe("setupSearch", () => {
|
||||
web: {
|
||||
search: {
|
||||
provider: "perplexity",
|
||||
perplexity: { apiKey: "existing-key" },
|
||||
perplexity: { apiKey: "existing-key" }, // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -142,7 +142,7 @@ describe("setupSearch", () => {
|
||||
search: {
|
||||
provider: "perplexity",
|
||||
enabled: false,
|
||||
perplexity: { apiKey: "existing-key" },
|
||||
perplexity: { apiKey: "existing-key" }, // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -162,7 +162,7 @@ describe("setupSearch", () => {
|
||||
web: {
|
||||
search: {
|
||||
provider: "perplexity",
|
||||
perplexity: { apiKey: "stored-pplx-key" },
|
||||
perplexity: { apiKey: "stored-pplx-key" }, // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -184,7 +184,7 @@ describe("setupSearch", () => {
|
||||
search: {
|
||||
provider: "perplexity",
|
||||
enabled: false,
|
||||
perplexity: { apiKey: "stored-pplx-key" },
|
||||
perplexity: { apiKey: "stored-pplx-key" }, // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -212,7 +212,7 @@ describe("setupSearch", () => {
|
||||
|
||||
it("quickstart skips key prompt when env var is available", async () => {
|
||||
const orig = process.env.BRAVE_API_KEY;
|
||||
process.env.BRAVE_API_KEY = "env-brave-key";
|
||||
process.env.BRAVE_API_KEY = "env-brave-key"; // pragma: allowlist secret
|
||||
try {
|
||||
const cfg: OpenClawConfig = {};
|
||||
const { prompter } = createPrompter({ selectValue: "brave" });
|
||||
@@ -235,13 +235,13 @@ describe("setupSearch", () => {
|
||||
const cfg: OpenClawConfig = {};
|
||||
const { prompter } = createPrompter({ selectValue: "perplexity" });
|
||||
const result = await setupSearch(cfg, runtime, prompter, {
|
||||
secretInputMode: "ref",
|
||||
secretInputMode: "ref", // pragma: allowlist secret
|
||||
});
|
||||
expect(result.tools?.web?.search?.provider).toBe("perplexity");
|
||||
expect(result.tools?.web?.search?.perplexity?.apiKey).toEqual({
|
||||
source: "env",
|
||||
provider: "default",
|
||||
id: "PERPLEXITY_API_KEY",
|
||||
id: "PERPLEXITY_API_KEY", // pragma: allowlist secret
|
||||
});
|
||||
expect(prompter.text).not.toHaveBeenCalled();
|
||||
});
|
||||
@@ -250,7 +250,7 @@ describe("setupSearch", () => {
|
||||
const cfg: OpenClawConfig = {};
|
||||
const { prompter } = createPrompter({ selectValue: "brave" });
|
||||
const result = await setupSearch(cfg, runtime, prompter, {
|
||||
secretInputMode: "ref",
|
||||
secretInputMode: "ref", // pragma: allowlist secret
|
||||
});
|
||||
expect(result.tools?.web?.search?.provider).toBe("brave");
|
||||
expect(result.tools?.web?.search?.apiKey).toEqual({
|
||||
|
||||
@@ -115,7 +115,8 @@ function resolveSearchSecretInput(
|
||||
key: string,
|
||||
secretInputMode?: SecretInputMode,
|
||||
): SecretInput {
|
||||
if (secretInputMode === "ref") {
|
||||
const useSecretRefMode = secretInputMode === "ref"; // pragma: allowlist secret
|
||||
if (useSecretRefMode) {
|
||||
return buildSearchEnvRef(provider);
|
||||
}
|
||||
return key;
|
||||
@@ -254,7 +255,8 @@ export async function setupSearch(
|
||||
return preserveDisabledState(config, result);
|
||||
}
|
||||
|
||||
if (opts?.secretInputMode === "ref") {
|
||||
const useSecretRefMode = opts?.secretInputMode === "ref"; // pragma: allowlist secret
|
||||
if (useSecretRefMode) {
|
||||
if (keyConfigured) {
|
||||
return preserveDisabledState(config, applyProviderOnly(config, choice));
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ export type NodeManagerChoice = "npm" | "pnpm" | "bun";
|
||||
export type ChannelChoice = ChannelId;
|
||||
// Legacy alias (pre-rename).
|
||||
export type ProviderChoice = ChannelChoice;
|
||||
export type SecretInputMode = "plaintext" | "ref";
|
||||
export type SecretInputMode = "plaintext" | "ref"; // pragma: allowlist secret
|
||||
|
||||
export type OnboardOptions = {
|
||||
mode?: OnboardMode;
|
||||
|
||||
@@ -47,7 +47,7 @@ describe("onboardCommand", () => {
|
||||
|
||||
await onboardCommand(
|
||||
{
|
||||
secretInputMode: "invalid" as never,
|
||||
secretInputMode: "invalid" as never, // pragma: allowlist secret
|
||||
},
|
||||
runtime,
|
||||
);
|
||||
|
||||
@@ -39,8 +39,8 @@ export async function onboardCommand(opts: OnboardOptions, runtime: RuntimeEnv =
|
||||
: { ...opts, authChoice: normalizedAuthChoice, flow };
|
||||
if (
|
||||
normalizedOpts.secretInputMode &&
|
||||
normalizedOpts.secretInputMode !== "plaintext" &&
|
||||
normalizedOpts.secretInputMode !== "ref"
|
||||
normalizedOpts.secretInputMode !== "plaintext" && // pragma: allowlist secret
|
||||
normalizedOpts.secretInputMode !== "ref" // pragma: allowlist secret
|
||||
) {
|
||||
runtime.error('Invalid --secret-input-mode. Use "plaintext" or "ref".');
|
||||
runtime.exit(1);
|
||||
|
||||
@@ -236,9 +236,9 @@ function makeHttpSlackUnavailablePlugin(): ChannelPlugin {
|
||||
botToken: "xoxb-http",
|
||||
signingSecret: "",
|
||||
botTokenSource: "config",
|
||||
signingSecretSource: "config",
|
||||
signingSecretSource: "config", // pragma: allowlist secret
|
||||
botTokenStatus: "available",
|
||||
signingSecretStatus: "configured_unavailable",
|
||||
signingSecretStatus: "configured_unavailable", // pragma: allowlist secret
|
||||
}),
|
||||
resolveAccount: () => ({
|
||||
name: "Primary",
|
||||
@@ -248,9 +248,9 @@ function makeHttpSlackUnavailablePlugin(): ChannelPlugin {
|
||||
botToken: "xoxb-http",
|
||||
signingSecret: "",
|
||||
botTokenSource: "config",
|
||||
signingSecretSource: "config",
|
||||
signingSecretSource: "config", // pragma: allowlist secret
|
||||
botTokenStatus: "available",
|
||||
signingSecretStatus: "configured_unavailable",
|
||||
signingSecretStatus: "configured_unavailable", // pragma: allowlist secret
|
||||
}),
|
||||
isConfigured: () => true,
|
||||
isEnabled: () => true,
|
||||
|
||||
@@ -177,7 +177,10 @@ const buildAccountNotes = (params: {
|
||||
if (snapshot.appTokenSource && snapshot.appTokenSource !== "none") {
|
||||
notes.push(`app:${snapshot.appTokenSource}`);
|
||||
}
|
||||
if (snapshot.signingSecretSource && snapshot.signingSecretSource !== "none") {
|
||||
if (
|
||||
snapshot.signingSecretSource &&
|
||||
snapshot.signingSecretSource !== "none" /* pragma: allowlist secret */
|
||||
) {
|
||||
notes.push(`signing:${snapshot.signingSecretSource}`);
|
||||
}
|
||||
if (hasConfiguredUnavailableCredentialStatus(entry.account)) {
|
||||
|
||||
@@ -150,7 +150,7 @@ export const FIELD_HELP: Record<string, string> = {
|
||||
"talk.providers.*.voiceAliases": "Optional provider voice alias map for Talk directives.",
|
||||
"talk.providers.*.modelId": "Provider default model ID for Talk mode.",
|
||||
"talk.providers.*.outputFormat": "Provider default output format for Talk mode.",
|
||||
"talk.providers.*.apiKey": "Provider API key for Talk mode.",
|
||||
"talk.providers.*.apiKey": "Provider API key for Talk mode.", // pragma: allowlist secret
|
||||
"talk.voiceId":
|
||||
"Legacy ElevenLabs default voice ID for Talk mode. Prefer talk.providers.elevenlabs.voiceId.",
|
||||
"talk.voiceAliases":
|
||||
@@ -651,7 +651,7 @@ export const FIELD_HELP: Record<string, string> = {
|
||||
"tools.web.search.gemini.apiKey":
|
||||
"Gemini API key for Google Search grounding (fallback: GEMINI_API_KEY env var).",
|
||||
"tools.web.search.gemini.model": 'Gemini model override (default: "gemini-2.5-flash").',
|
||||
"tools.web.search.grok.apiKey": "Grok (xAI) API key (fallback: XAI_API_KEY env var).",
|
||||
"tools.web.search.grok.apiKey": "Grok (xAI) API key (fallback: XAI_API_KEY env var).", // pragma: allowlist secret
|
||||
"tools.web.search.grok.model": 'Grok model override (default: "grok-4-1-fast").',
|
||||
"tools.web.search.kimi.apiKey":
|
||||
"Moonshot/Kimi API key (fallback: KIMI_API_KEY or MOONSHOT_API_KEY env var).",
|
||||
|
||||
@@ -217,14 +217,14 @@ export const FIELD_LABELS: Record<string, string> = {
|
||||
"tools.web.search.maxResults": "Web Search Max Results",
|
||||
"tools.web.search.timeoutSeconds": "Web Search Timeout (sec)",
|
||||
"tools.web.search.cacheTtlMinutes": "Web Search Cache TTL (min)",
|
||||
"tools.web.search.perplexity.apiKey": "Perplexity API Key",
|
||||
"tools.web.search.perplexity.apiKey": "Perplexity API Key", // pragma: allowlist secret
|
||||
"tools.web.search.perplexity.baseUrl": "Perplexity Base URL",
|
||||
"tools.web.search.perplexity.model": "Perplexity Model",
|
||||
"tools.web.search.gemini.apiKey": "Gemini Search API Key",
|
||||
"tools.web.search.gemini.apiKey": "Gemini Search API Key", // pragma: allowlist secret
|
||||
"tools.web.search.gemini.model": "Gemini Search Model",
|
||||
"tools.web.search.grok.apiKey": "Grok Search API Key",
|
||||
"tools.web.search.grok.apiKey": "Grok Search API Key", // pragma: allowlist secret
|
||||
"tools.web.search.grok.model": "Grok Search Model",
|
||||
"tools.web.search.kimi.apiKey": "Kimi Search API Key",
|
||||
"tools.web.search.kimi.apiKey": "Kimi Search API Key", // pragma: allowlist secret
|
||||
"tools.web.search.kimi.baseUrl": "Kimi Search Base URL",
|
||||
"tools.web.search.kimi.model": "Kimi Search Model",
|
||||
"tools.web.fetch.enabled": "Enable Web Fetch Tool",
|
||||
@@ -236,7 +236,7 @@ export const FIELD_LABELS: Record<string, string> = {
|
||||
"tools.web.fetch.userAgent": "Web Fetch User-Agent",
|
||||
"tools.web.fetch.readability": "Web Fetch Readability Extraction",
|
||||
"tools.web.fetch.firecrawl.enabled": "Enable Firecrawl Fallback",
|
||||
"tools.web.fetch.firecrawl.apiKey": "Firecrawl API Key",
|
||||
"tools.web.fetch.firecrawl.apiKey": "Firecrawl API Key", // pragma: allowlist secret
|
||||
"tools.web.fetch.firecrawl.baseUrl": "Firecrawl Base URL",
|
||||
"tools.web.fetch.firecrawl.onlyMainContent": "Firecrawl Main Content Only",
|
||||
"tools.web.fetch.firecrawl.maxAgeMs": "Firecrawl Cache Max Age (ms)",
|
||||
@@ -411,7 +411,7 @@ export const FIELD_LABELS: Record<string, string> = {
|
||||
"models.mode": "Model Catalog Mode",
|
||||
"models.providers": "Model Providers",
|
||||
"models.providers.*.baseUrl": "Model Provider Base URL",
|
||||
"models.providers.*.apiKey": "Model Provider API Key",
|
||||
"models.providers.*.apiKey": "Model Provider API Key", // pragma: allowlist secret
|
||||
"models.providers.*.auth": "Model Provider Auth Mode",
|
||||
"models.providers.*.api": "Model Provider API Adapter",
|
||||
"models.providers.*.injectNumCtxForOpenAICompat": "Model Provider Inject num_ctx (OpenAI Compat)",
|
||||
@@ -484,7 +484,7 @@ export const FIELD_LABELS: Record<string, string> = {
|
||||
"commands.useAccessGroups": "Use Access Groups",
|
||||
"commands.ownerAllowFrom": "Command Owners",
|
||||
"commands.ownerDisplay": "Owner ID Display",
|
||||
"commands.ownerDisplaySecret": "Owner ID Hash Secret",
|
||||
"commands.ownerDisplaySecret": "Owner ID Hash Secret", // pragma: allowlist secret
|
||||
"commands.allowFrom": "Command Elevated Access Rules",
|
||||
ui: "UI",
|
||||
"ui.seamColor": "Accent Color",
|
||||
@@ -679,8 +679,8 @@ export const FIELD_LABELS: Record<string, string> = {
|
||||
"talk.providers.*.voiceAliases": "Talk Provider Voice Aliases",
|
||||
"talk.providers.*.modelId": "Talk Provider Model ID",
|
||||
"talk.providers.*.outputFormat": "Talk Provider Output Format",
|
||||
"talk.providers.*.apiKey": "Talk Provider API Key",
|
||||
"talk.apiKey": "Talk API Key",
|
||||
"talk.providers.*.apiKey": "Talk Provider API Key", // pragma: allowlist secret
|
||||
"talk.apiKey": "Talk API Key", // pragma: allowlist secret
|
||||
channels: "Channels",
|
||||
"channels.defaults": "Channel Defaults",
|
||||
"channels.defaults.groupPolicy": "Default Group Policy",
|
||||
@@ -823,7 +823,7 @@ export const FIELD_LABELS: Record<string, string> = {
|
||||
"plugins.entries.*.enabled": "Plugin Enabled",
|
||||
"plugins.entries.*.hooks": "Plugin Hook Policy",
|
||||
"plugins.entries.*.hooks.allowPromptInjection": "Allow Prompt Injection Hooks",
|
||||
"plugins.entries.*.apiKey": "Plugin API Key",
|
||||
"plugins.entries.*.apiKey": "Plugin API Key", // pragma: allowlist secret
|
||||
"plugins.entries.*.env": "Plugin Environment Variables",
|
||||
"plugins.entries.*.config": "Plugin Config",
|
||||
"plugins.installs": "Plugin Install Records",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export type SecretRefSource = "env" | "file" | "exec";
|
||||
export type SecretRefSource = "env" | "file" | "exec"; // pragma: allowlist secret
|
||||
|
||||
/**
|
||||
* Stable identifier for a secret in a configured source.
|
||||
@@ -14,7 +14,7 @@ export type SecretRef = {
|
||||
};
|
||||
|
||||
export type SecretInput = string | SecretRef;
|
||||
export const DEFAULT_SECRET_PROVIDER_ALIAS = "default";
|
||||
export const DEFAULT_SECRET_PROVIDER_ALIAS = "default"; // pragma: allowlist secret
|
||||
export const ENV_SECRET_REF_ID_RE = /^[A-Z][A-Z0-9_]{0,127}$/;
|
||||
const ENV_SECRET_TEMPLATE_RE = /^\$\{([A-Z][A-Z0-9_]{0,127})\}$/;
|
||||
type SecretDefaults = {
|
||||
@@ -179,7 +179,7 @@ export type EnvSecretProviderConfig = {
|
||||
allowlist?: string[];
|
||||
};
|
||||
|
||||
export type FileSecretProviderMode = "singleValue" | "json";
|
||||
export type FileSecretProviderMode = "singleValue" | "json"; // pragma: allowlist secret
|
||||
|
||||
export type FileSecretProviderConfig = {
|
||||
source: "file";
|
||||
|
||||
@@ -13,7 +13,7 @@ describe("gateway auth mode policy", () => {
|
||||
auth: {
|
||||
mode: "token",
|
||||
token: "token-value",
|
||||
password: "password-value",
|
||||
password: "password-value", // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -36,7 +36,7 @@ describe("gateway auth mode policy", () => {
|
||||
gateway: {
|
||||
auth: {
|
||||
token: "token-value",
|
||||
password: "password-value",
|
||||
password: "password-value", // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -65,7 +65,7 @@ describe("gateway auth mode policy", () => {
|
||||
gateway: {
|
||||
auth: {
|
||||
token: "token-value",
|
||||
password: "password-value",
|
||||
password: "password-value", // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -252,7 +252,7 @@ export function resolveGatewayAuth(params: {
|
||||
env,
|
||||
includeLegacyEnv: false,
|
||||
tokenPrecedence: "config-first",
|
||||
passwordPrecedence: "config-first",
|
||||
passwordPrecedence: "config-first", // pragma: allowlist secret
|
||||
});
|
||||
const token = resolvedCredentials.token;
|
||||
const password = resolvedCredentials.password;
|
||||
|
||||
@@ -358,7 +358,7 @@ async function resolveGatewayCredentialsWithEnv(
|
||||
explicitAuth: context.explicitAuth,
|
||||
urlOverride: context.urlOverride,
|
||||
urlOverrideSource: context.urlOverrideSource,
|
||||
remotePasswordPrecedence: "env-first",
|
||||
remotePasswordPrecedence: "env-first", // pragma: allowlist secret
|
||||
});
|
||||
}
|
||||
|
||||
@@ -487,7 +487,7 @@ async function resolveGatewayCredentialsWithEnv(
|
||||
explicitAuth: context.explicitAuth,
|
||||
urlOverride: context.urlOverride,
|
||||
urlOverrideSource: context.urlOverrideSource,
|
||||
remotePasswordPrecedence: "env-first",
|
||||
remotePasswordPrecedence: "env-first", // pragma: allowlist secret
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ export type GatewayCredentialPrecedence = "env-first" | "config-first";
|
||||
export type GatewayRemoteCredentialPrecedence = "remote-first" | "env-first";
|
||||
export type GatewayRemoteCredentialFallback = "remote-env-local" | "remote-only";
|
||||
|
||||
const GATEWAY_SECRET_REF_UNAVAILABLE_ERROR_CODE = "GATEWAY_SECRET_REF_UNAVAILABLE";
|
||||
const GATEWAY_SECRET_REF_UNAVAILABLE_ERROR_CODE = "GATEWAY_SECRET_REF_UNAVAILABLE"; // pragma: allowlist secret
|
||||
|
||||
export class GatewaySecretRefUnavailableError extends Error {
|
||||
readonly code = GATEWAY_SECRET_REF_UNAVAILABLE_ERROR_CODE;
|
||||
@@ -119,7 +119,7 @@ export function resolveGatewayCredentialsFromValues(params: {
|
||||
? firstDefined([configToken, envToken])
|
||||
: firstDefined([envToken, configToken]);
|
||||
const password =
|
||||
passwordPrecedence === "config-first"
|
||||
passwordPrecedence === "config-first" // pragma: allowlist secret
|
||||
? firstDefined([configPassword, envPassword])
|
||||
: firstDefined([envPassword, configPassword]);
|
||||
|
||||
@@ -158,7 +158,7 @@ export function resolveGatewayCredentialsFromConfig(params: {
|
||||
env,
|
||||
includeLegacyEnv,
|
||||
tokenPrecedence: "env-first",
|
||||
passwordPrecedence: "env-first",
|
||||
passwordPrecedence: "env-first", // pragma: allowlist secret
|
||||
});
|
||||
}
|
||||
|
||||
@@ -243,9 +243,9 @@ export function resolveGatewayCredentialsFromConfig(params: {
|
||||
? firstDefined([envToken, remoteToken, localToken])
|
||||
: firstDefined([remoteToken, envToken, localToken]);
|
||||
const password =
|
||||
remotePasswordFallback === "remote-only"
|
||||
remotePasswordFallback === "remote-only" // pragma: allowlist secret
|
||||
? remotePassword
|
||||
: remotePasswordPrecedence === "env-first"
|
||||
: remotePasswordPrecedence === "env-first" // pragma: allowlist secret
|
||||
? firstDefined([envPassword, remotePassword, localPassword])
|
||||
: firstDefined([remotePassword, envPassword, localPassword]);
|
||||
|
||||
@@ -255,7 +255,7 @@ export function resolveGatewayCredentialsFromConfig(params: {
|
||||
const localTokenFallbackEnabled = remoteTokenFallback !== "remote-only";
|
||||
const localTokenFallback = remoteTokenFallback === "remote-only" ? undefined : localToken;
|
||||
const localPasswordFallback =
|
||||
remotePasswordFallback === "remote-only" ? undefined : localPassword;
|
||||
remotePasswordFallback === "remote-only" ? undefined : localPassword; // pragma: allowlist secret
|
||||
if (remoteTokenRef && !token && !envToken && !localTokenFallback && !password) {
|
||||
throwUnresolvedGatewaySecretInput("gateway.remote.token");
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ export const ConnectErrorDetailCodes = {
|
||||
AUTH_TOKEN_MISSING: "AUTH_TOKEN_MISSING",
|
||||
AUTH_TOKEN_MISMATCH: "AUTH_TOKEN_MISMATCH",
|
||||
AUTH_TOKEN_NOT_CONFIGURED: "AUTH_TOKEN_NOT_CONFIGURED",
|
||||
AUTH_PASSWORD_MISSING: "AUTH_PASSWORD_MISSING",
|
||||
AUTH_PASSWORD_MISMATCH: "AUTH_PASSWORD_MISMATCH",
|
||||
AUTH_PASSWORD_NOT_CONFIGURED: "AUTH_PASSWORD_NOT_CONFIGURED",
|
||||
AUTH_PASSWORD_MISSING: "AUTH_PASSWORD_MISSING", // pragma: allowlist secret
|
||||
AUTH_PASSWORD_MISMATCH: "AUTH_PASSWORD_MISMATCH", // pragma: allowlist secret
|
||||
AUTH_PASSWORD_NOT_CONFIGURED: "AUTH_PASSWORD_NOT_CONFIGURED", // pragma: allowlist secret
|
||||
AUTH_DEVICE_TOKEN_MISMATCH: "AUTH_DEVICE_TOKEN_MISMATCH",
|
||||
AUTH_RATE_LIMITED: "AUTH_RATE_LIMITED",
|
||||
AUTH_TAILSCALE_IDENTITY_MISSING: "AUTH_TAILSCALE_IDENTITY_MISSING",
|
||||
|
||||
@@ -3,7 +3,7 @@ import { resolveSecretInputRef } from "../config/types.secrets.js";
|
||||
import { secretRefKey } from "../secrets/ref-contract.js";
|
||||
import { resolveSecretRefValues } from "../secrets/resolve.js";
|
||||
|
||||
export type SecretInputUnresolvedReasonStyle = "generic" | "detailed";
|
||||
export type SecretInputUnresolvedReasonStyle = "generic" | "detailed"; // pragma: allowlist secret
|
||||
|
||||
function trimToUndefined(value: unknown): string | undefined {
|
||||
if (typeof value !== "string") {
|
||||
|
||||
@@ -115,7 +115,7 @@ function mockSuccessfulWakeConfig(nodeId: string) {
|
||||
value: {
|
||||
teamId: "TEAM123",
|
||||
keyId: "KEY123",
|
||||
privateKey: "-----BEGIN PRIVATE KEY-----\nabc\n-----END PRIVATE KEY-----",
|
||||
privateKey: "-----BEGIN PRIVATE KEY-----\nabc\n-----END PRIVATE KEY-----", // pragma: allowlist secret
|
||||
},
|
||||
});
|
||||
mocks.sendApnsBackgroundWake.mockResolvedValue({
|
||||
|
||||
@@ -20,7 +20,7 @@ export function registerAuthModesSuite(): void {
|
||||
let port: number;
|
||||
|
||||
beforeAll(async () => {
|
||||
testState.gatewayAuth = { mode: "password", password: "secret" };
|
||||
testState.gatewayAuth = { mode: "password", password: "secret" }; // pragma: allowlist secret
|
||||
port = await getFreePort();
|
||||
server = await startGatewayServer(port);
|
||||
});
|
||||
@@ -31,14 +31,14 @@ export function registerAuthModesSuite(): void {
|
||||
|
||||
test("accepts password auth when configured", async () => {
|
||||
const ws = await openWs(port);
|
||||
const res = await connectReq(ws, { password: "secret" });
|
||||
const res = await connectReq(ws, { password: "secret" }); // pragma: allowlist secret
|
||||
expect(res.ok).toBe(true);
|
||||
ws.close();
|
||||
});
|
||||
|
||||
test("rejects invalid password", async () => {
|
||||
const ws = await openWs(port);
|
||||
const res = await connectReq(ws, { password: "wrong" });
|
||||
const res = await connectReq(ws, { password: "wrong" }); // pragma: allowlist secret
|
||||
expect(res.ok).toBe(false);
|
||||
expect(res.error?.message ?? "").toContain("unauthorized");
|
||||
ws.close();
|
||||
|
||||
@@ -465,7 +465,7 @@ describe("gateway hot reload", () => {
|
||||
serverOptions: {
|
||||
auth: {
|
||||
mode: "password",
|
||||
password: "override-password",
|
||||
password: "override-password", // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -486,7 +486,7 @@ describe("gateway hot reload", () => {
|
||||
|
||||
it("emits one-shot degraded and recovered system events during secret reload transitions", async () => {
|
||||
await writeEnvRefConfig();
|
||||
process.env.OPENAI_API_KEY = "sk-startup";
|
||||
process.env.OPENAI_API_KEY = "sk-startup"; // pragma: allowlist secret
|
||||
|
||||
await withGatewayServer(async () => {
|
||||
const onHotReload = hoisted.getOnHotReload();
|
||||
@@ -531,7 +531,7 @@ describe("gateway hot reload", () => {
|
||||
);
|
||||
expect(drainSystemEvents(sessionKey)).toEqual([]);
|
||||
|
||||
process.env.OPENAI_API_KEY = "sk-recovered";
|
||||
process.env.OPENAI_API_KEY = "sk-recovered"; // pragma: allowlist secret
|
||||
await expect(onHotReload?.(plan, nextConfig)).resolves.toBeUndefined();
|
||||
const recoveredEvents = drainSystemEvents(sessionKey);
|
||||
expect(recoveredEvents.some((event) => event.includes("[SECRETS_RELOADER_RECOVERED]"))).toBe(
|
||||
@@ -542,7 +542,7 @@ describe("gateway hot reload", () => {
|
||||
|
||||
it("serves secrets.reload immediately after startup without race failures", async () => {
|
||||
await writeEnvRefConfig();
|
||||
process.env.OPENAI_API_KEY = "sk-startup";
|
||||
process.env.OPENAI_API_KEY = "sk-startup"; // pragma: allowlist secret
|
||||
const { server, ws } = await startServerWithClient();
|
||||
try {
|
||||
await connectOk(ws);
|
||||
|
||||
@@ -33,9 +33,9 @@ function makeSlackHttpSummaryPlugin(): ChannelPlugin {
|
||||
botToken: "xoxb-http",
|
||||
signingSecret: "",
|
||||
botTokenSource: "config",
|
||||
signingSecretSource: "config",
|
||||
signingSecretSource: "config", // pragma: allowlist secret
|
||||
botTokenStatus: "available",
|
||||
signingSecretStatus: "configured_unavailable",
|
||||
signingSecretStatus: "configured_unavailable", // pragma: allowlist secret
|
||||
}
|
||||
: {
|
||||
accountId: "primary",
|
||||
|
||||
@@ -69,7 +69,10 @@ const buildAccountDetails = (params: {
|
||||
if (snapshot.appTokenSource && snapshot.appTokenSource !== "none") {
|
||||
details.push(`app:${snapshot.appTokenSource}`);
|
||||
}
|
||||
if (snapshot.signingSecretSource && snapshot.signingSecretSource !== "none") {
|
||||
if (
|
||||
snapshot.signingSecretSource &&
|
||||
snapshot.signingSecretSource !== "none" /* pragma: allowlist secret */
|
||||
) {
|
||||
details.push(`signing:${snapshot.signingSecretSource}`);
|
||||
}
|
||||
if (hasConfiguredUnavailableCredentialStatus(params.entry.account)) {
|
||||
|
||||
@@ -248,17 +248,17 @@ describe("resolveProviderAuths key normalization", () => {
|
||||
zai: {
|
||||
baseUrl: "https://api.z.ai",
|
||||
models: [modelDef],
|
||||
apiKey: "cfg-zai-key",
|
||||
apiKey: "cfg-zai-key", // pragma: allowlist secret
|
||||
},
|
||||
minimax: {
|
||||
baseUrl: "https://api.minimaxi.com",
|
||||
models: [modelDef],
|
||||
apiKey: "cfg-minimax-key",
|
||||
apiKey: "cfg-minimax-key", // pragma: allowlist secret
|
||||
},
|
||||
xiaomi: {
|
||||
baseUrl: "https://api.xiaomi.example",
|
||||
models: [modelDef],
|
||||
apiKey: "cfg-xiaomi-key",
|
||||
apiKey: "cfg-xiaomi-key", // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -16,7 +16,7 @@ describe("describeMoonshotVideo", () => {
|
||||
const result = await describeMoonshotVideo({
|
||||
buffer: Buffer.from("video-bytes"),
|
||||
fileName: "clip.mp4",
|
||||
apiKey: "moonshot-test",
|
||||
apiKey: "moonshot-test", // pragma: allowlist secret
|
||||
timeoutMs: 1500,
|
||||
baseUrl: "https://api.moonshot.ai/v1/",
|
||||
model: "kimi-k2.5",
|
||||
@@ -61,7 +61,7 @@ describe("describeMoonshotVideo", () => {
|
||||
const result = await describeMoonshotVideo({
|
||||
buffer: Buffer.from("video"),
|
||||
fileName: "clip.mp4",
|
||||
apiKey: "moonshot-test",
|
||||
apiKey: "moonshot-test", // pragma: allowlist secret
|
||||
timeoutMs: 1000,
|
||||
fetchFn,
|
||||
});
|
||||
|
||||
@@ -120,7 +120,7 @@ describe("runCapability auto audio entries", () => {
|
||||
delete process.env.GROQ_API_KEY;
|
||||
delete process.env.DEEPGRAM_API_KEY;
|
||||
delete process.env.GEMINI_API_KEY;
|
||||
process.env.MISTRAL_API_KEY = "mistral-test-key";
|
||||
process.env.MISTRAL_API_KEY = "mistral-test-key"; // pragma: allowlist secret
|
||||
let runResult: Awaited<ReturnType<typeof runCapability>> | undefined;
|
||||
try {
|
||||
await withAudioFixture("openclaw-auto-audio-mistral", async ({ ctx, media, cache }) => {
|
||||
@@ -140,7 +140,7 @@ describe("runCapability auto audio entries", () => {
|
||||
models: {
|
||||
providers: {
|
||||
mistral: {
|
||||
apiKey: "mistral-test-key",
|
||||
apiKey: "mistral-test-key", // pragma: allowlist secret
|
||||
models: [],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -25,7 +25,7 @@ async function runAudioCapabilityWithFetchCapture(params: {
|
||||
models: {
|
||||
providers: {
|
||||
openai: {
|
||||
apiKey: "test-key",
|
||||
apiKey: "test-key", // pragma: allowlist secret
|
||||
models: [],
|
||||
},
|
||||
},
|
||||
@@ -80,7 +80,7 @@ describe("runCapability proxy fetch passthrough", () => {
|
||||
models: {
|
||||
providers: {
|
||||
moonshot: {
|
||||
apiKey: "test-key",
|
||||
apiKey: "test-key", // pragma: allowlist secret
|
||||
models: [],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -52,7 +52,7 @@ const AUDIO_CAPABILITY_CFG = {
|
||||
models: {
|
||||
providers: {
|
||||
openai: {
|
||||
apiKey: "test-key",
|
||||
apiKey: "test-key", // pragma: allowlist secret
|
||||
models: [],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -233,7 +233,7 @@ describe("embedding provider remote overrides", () => {
|
||||
config: {} as never,
|
||||
provider: "gemini",
|
||||
remote: {
|
||||
apiKey: "GEMINI_API_KEY",
|
||||
apiKey: "GEMINI_API_KEY", // pragma: allowlist secret
|
||||
},
|
||||
model: "text-embedding-004",
|
||||
fallback: "openai",
|
||||
@@ -266,7 +266,7 @@ describe("embedding provider remote overrides", () => {
|
||||
config: cfg as never,
|
||||
provider: "mistral",
|
||||
remote: {
|
||||
apiKey: "mistral-key",
|
||||
apiKey: "mistral-key", // pragma: allowlist secret
|
||||
},
|
||||
model: "mistral/mistral-embed",
|
||||
fallback: "none",
|
||||
@@ -356,7 +356,7 @@ describe("embedding provider auto selection", () => {
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
vi.mocked(authModule.resolveApiKeyForProvider).mockImplementation(async ({ provider }) => {
|
||||
if (provider === "mistral") {
|
||||
return { apiKey: "mistral-key", source: "env: MISTRAL_API_KEY", mode: "api-key" };
|
||||
return { apiKey: "mistral-key", source: "env: MISTRAL_API_KEY", mode: "api-key" }; // pragma: allowlist secret
|
||||
}
|
||||
throw new Error(`No API key found for provider "${provider}".`);
|
||||
});
|
||||
|
||||
@@ -298,7 +298,8 @@ function applyConfigTargetMutations(params: {
|
||||
}
|
||||
|
||||
const targetPathSegments = resolved.pathSegments;
|
||||
if (resolved.entry.secretShape === "sibling_ref") {
|
||||
const usesSiblingRef = resolved.entry.secretShape === "sibling_ref"; // pragma: allowlist secret
|
||||
if (usesSiblingRef) {
|
||||
const previous = getPath(params.nextConfig, targetPathSegments);
|
||||
if (isNonEmptyString(previous)) {
|
||||
scrubbedValues.add(previous.trim());
|
||||
@@ -530,7 +531,8 @@ function applyAuthProfileTargetMutation(params: {
|
||||
store,
|
||||
});
|
||||
const targetPathSegments = params.resolved.pathSegments;
|
||||
if (params.resolved.entry.secretShape === "sibling_ref") {
|
||||
const usesSiblingRef = params.resolved.entry.secretShape === "sibling_ref"; // pragma: allowlist secret
|
||||
if (usesSiblingRef) {
|
||||
const previous = getPath(store, targetPathSegments);
|
||||
if (isNonEmptyString(previous)) {
|
||||
params.scrubbedValues.add(previous.trim());
|
||||
|
||||
@@ -53,7 +53,7 @@ async function createAuditFixture(): Promise<AuditFixture> {
|
||||
env: {
|
||||
OPENCLAW_STATE_DIR: stateDir,
|
||||
OPENCLAW_CONFIG_PATH: configPath,
|
||||
OPENAI_API_KEY: "env-openai-key",
|
||||
OPENAI_API_KEY: "env-openai-key", // pragma: allowlist secret
|
||||
PATH: resolveRuntimePathEnv(),
|
||||
},
|
||||
};
|
||||
@@ -146,7 +146,7 @@ describe("secrets audit", () => {
|
||||
"#!/bin/sh",
|
||||
`printf 'x\\n' >> ${JSON.stringify(execLogPath)}`,
|
||||
"cat >/dev/null",
|
||||
'printf \'{"protocolVersion":1,"values":{"providers/openai/apiKey":"value:providers/openai/apiKey","providers/moonshot/apiKey":"value:providers/moonshot/apiKey"}}\'',
|
||||
'printf \'{"protocolVersion":1,"values":{"providers/openai/apiKey":"value:providers/openai/apiKey","providers/moonshot/apiKey":"value:providers/moonshot/apiKey"}}\'', // pragma: allowlist secret
|
||||
].join("\n"),
|
||||
{ encoding: "utf8", mode: 0o700 },
|
||||
);
|
||||
|
||||
@@ -36,7 +36,7 @@ export type SecretsAuditCode =
|
||||
| "REF_SHADOWED"
|
||||
| "LEGACY_RESIDUE";
|
||||
|
||||
export type SecretsAuditSeverity = "info" | "warn" | "error";
|
||||
export type SecretsAuditSeverity = "info" | "warn" | "error"; // pragma: allowlist secret
|
||||
|
||||
export type SecretsAuditFinding = {
|
||||
code: SecretsAuditCode;
|
||||
@@ -48,7 +48,7 @@ export type SecretsAuditFinding = {
|
||||
profileId?: string;
|
||||
};
|
||||
|
||||
export type SecretsAuditStatus = "clean" | "findings" | "unresolved";
|
||||
export type SecretsAuditStatus = "clean" | "findings" | "unresolved"; // pragma: allowlist secret
|
||||
|
||||
export type SecretsAuditReport = {
|
||||
version: 1;
|
||||
|
||||
@@ -79,7 +79,9 @@ export function analyzeCommandSecretAssignmentsFromSnapshot(params: {
|
||||
value: resolved,
|
||||
});
|
||||
|
||||
if (target.entry.secretShape === "sibling_ref" && explicitRef && inlineCandidateRef) {
|
||||
const hasCompetingSiblingRef =
|
||||
target.entry.secretShape === "sibling_ref" && explicitRef && inlineCandidateRef; // pragma: allowlist secret
|
||||
if (hasCompetingSiblingRef) {
|
||||
diagnostics.push(
|
||||
`${target.path}: both inline and sibling ref were present; sibling ref took precedence.`,
|
||||
);
|
||||
|
||||
@@ -6,7 +6,7 @@ type CredentialMatrixEntry = {
|
||||
path: string;
|
||||
refPath?: string;
|
||||
when?: { type: "api_key" | "token" };
|
||||
secretShape: "secret_input" | "sibling_ref";
|
||||
secretShape: "secret_input" | "sibling_ref"; // pragma: allowlist secret
|
||||
optIn: true;
|
||||
notes?: string;
|
||||
};
|
||||
|
||||
@@ -153,7 +153,7 @@ describe("secret ref resolver", () => {
|
||||
{ source: "env", provider: "default", id: "OPENAI_API_KEY" },
|
||||
{
|
||||
config,
|
||||
env: { OPENAI_API_KEY: "sk-env-value" },
|
||||
env: { OPENAI_API_KEY: "sk-env-value" }, // pragma: allowlist secret
|
||||
},
|
||||
);
|
||||
expect(value).toBe("sk-env-value");
|
||||
@@ -167,7 +167,7 @@ describe("secret ref resolver", () => {
|
||||
JSON.stringify({
|
||||
providers: {
|
||||
openai: {
|
||||
apiKey: "sk-file-value",
|
||||
apiKey: "sk-file-value", // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -375,7 +375,7 @@ describe("secret ref resolver", () => {
|
||||
JSON.stringify({
|
||||
providers: {
|
||||
openai: {
|
||||
apiKey: "sk-file-value",
|
||||
apiKey: "sk-file-value", // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -122,21 +122,21 @@ describe("secrets runtime snapshot", () => {
|
||||
const snapshot = await prepareSecretsRuntimeSnapshot({
|
||||
config,
|
||||
env: {
|
||||
OPENAI_API_KEY: "sk-env-openai",
|
||||
GITHUB_TOKEN: "ghp-env-token",
|
||||
REVIEW_SKILL_API_KEY: "sk-skill-ref",
|
||||
MEMORY_REMOTE_API_KEY: "mem-ref-key",
|
||||
TALK_API_KEY: "talk-ref-key",
|
||||
TALK_PROVIDER_API_KEY: "talk-provider-ref-key",
|
||||
OPENAI_API_KEY: "sk-env-openai", // pragma: allowlist secret
|
||||
GITHUB_TOKEN: "ghp-env-token", // pragma: allowlist secret
|
||||
REVIEW_SKILL_API_KEY: "sk-skill-ref", // pragma: allowlist secret
|
||||
MEMORY_REMOTE_API_KEY: "mem-ref-key", // pragma: allowlist secret
|
||||
TALK_API_KEY: "talk-ref-key", // pragma: allowlist secret
|
||||
TALK_PROVIDER_API_KEY: "talk-provider-ref-key", // pragma: allowlist secret
|
||||
REMOTE_GATEWAY_TOKEN: "remote-token-ref",
|
||||
REMOTE_GATEWAY_PASSWORD: "remote-password-ref",
|
||||
REMOTE_GATEWAY_PASSWORD: "remote-password-ref", // pragma: allowlist secret
|
||||
TELEGRAM_BOT_TOKEN_REF: "telegram-bot-ref",
|
||||
TELEGRAM_WEBHOOK_SECRET_REF: "telegram-webhook-ref",
|
||||
TELEGRAM_WEBHOOK_SECRET_REF: "telegram-webhook-ref", // pragma: allowlist secret
|
||||
TELEGRAM_WORK_BOT_TOKEN_REF: "telegram-work-ref",
|
||||
SLACK_SIGNING_SECRET_REF: "slack-signing-ref",
|
||||
SLACK_SIGNING_SECRET_REF: "slack-signing-ref", // pragma: allowlist secret
|
||||
SLACK_WORK_BOT_TOKEN_REF: "slack-work-bot-ref",
|
||||
SLACK_WORK_APP_TOKEN_REF: "slack-work-app-ref",
|
||||
WEB_SEARCH_API_KEY: "web-search-ref",
|
||||
WEB_SEARCH_API_KEY: "web-search-ref", // pragma: allowlist secret
|
||||
},
|
||||
agentDirs: ["/tmp/openclaw-agent-main"],
|
||||
loadAuthStore: () =>
|
||||
@@ -305,7 +305,7 @@ describe("secrets runtime snapshot", () => {
|
||||
},
|
||||
}),
|
||||
env: {
|
||||
WEB_SEARCH_API_KEY: "web-search-ref",
|
||||
WEB_SEARCH_API_KEY: "web-search-ref", // pragma: allowlist secret
|
||||
},
|
||||
agentDirs: ["/tmp/openclaw-agent-main"],
|
||||
loadAuthStore: () => ({ version: 1, profiles: {} }),
|
||||
@@ -343,8 +343,8 @@ describe("secrets runtime snapshot", () => {
|
||||
},
|
||||
}),
|
||||
env: {
|
||||
WEB_SEARCH_API_KEY: "web-search-ref",
|
||||
WEB_SEARCH_GEMINI_API_KEY: "web-search-gemini-ref",
|
||||
WEB_SEARCH_API_KEY: "web-search-ref", // pragma: allowlist secret
|
||||
WEB_SEARCH_GEMINI_API_KEY: "web-search-gemini-ref", // pragma: allowlist secret
|
||||
},
|
||||
agentDirs: ["/tmp/openclaw-agent-main"],
|
||||
loadAuthStore: () => ({ version: 1, profiles: {} }),
|
||||
@@ -374,7 +374,7 @@ describe("secrets runtime snapshot", () => {
|
||||
},
|
||||
}),
|
||||
env: {
|
||||
WEB_SEARCH_GEMINI_API_KEY: "web-search-gemini-ref",
|
||||
WEB_SEARCH_GEMINI_API_KEY: "web-search-gemini-ref", // pragma: allowlist secret
|
||||
},
|
||||
agentDirs: ["/tmp/openclaw-agent-main"],
|
||||
loadAuthStore: () => ({ version: 1, profiles: {} }),
|
||||
@@ -399,7 +399,7 @@ describe("secrets runtime snapshot", () => {
|
||||
{
|
||||
providers: {
|
||||
openai: {
|
||||
apiKey: "sk-from-file-provider",
|
||||
apiKey: "sk-from-file-provider", // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -494,7 +494,7 @@ describe("secrets runtime snapshot", () => {
|
||||
},
|
||||
},
|
||||
}),
|
||||
env: { OPENAI_API_KEY: "sk-runtime" },
|
||||
env: { OPENAI_API_KEY: "sk-runtime" }, // pragma: allowlist secret
|
||||
agentDirs: ["/tmp/openclaw-agent-main"],
|
||||
loadAuthStore: () =>
|
||||
loadAuthStoreWithProfiles({
|
||||
@@ -603,7 +603,7 @@ describe("secrets runtime snapshot", () => {
|
||||
auth: {
|
||||
mode: "password",
|
||||
token: "local-token",
|
||||
password: "local-password",
|
||||
password: "local-password", // pragma: allowlist secret
|
||||
},
|
||||
remote: {
|
||||
enabled: true,
|
||||
@@ -642,7 +642,7 @@ describe("secrets runtime snapshot", () => {
|
||||
},
|
||||
}),
|
||||
env: {
|
||||
GATEWAY_PASSWORD_REF: "resolved-gateway-password",
|
||||
GATEWAY_PASSWORD_REF: "resolved-gateway-password", // pragma: allowlist secret
|
||||
},
|
||||
agentDirs: ["/tmp/openclaw-agent-main"],
|
||||
loadAuthStore: () => ({ version: 1, profiles: {} }),
|
||||
@@ -680,7 +680,7 @@ describe("secrets runtime snapshot", () => {
|
||||
auth: {
|
||||
mode: "password",
|
||||
token: { source: "env", provider: "default", id: "GATEWAY_TOKEN_REF" },
|
||||
password: "password-123",
|
||||
password: "password-123", // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -728,7 +728,7 @@ describe("secrets runtime snapshot", () => {
|
||||
},
|
||||
}),
|
||||
env: {
|
||||
GATEWAY_PASSWORD_REF: "resolved-gateway-password",
|
||||
GATEWAY_PASSWORD_REF: "resolved-gateway-password", // pragma: allowlist secret
|
||||
},
|
||||
agentDirs: ["/tmp/openclaw-agent-main"],
|
||||
loadAuthStore: () => ({ version: 1, profiles: {} }),
|
||||
@@ -822,7 +822,7 @@ describe("secrets runtime snapshot", () => {
|
||||
}),
|
||||
env: {
|
||||
REMOTE_TOKEN: "resolved-remote-token",
|
||||
REMOTE_PASSWORD: "resolved-remote-password",
|
||||
REMOTE_PASSWORD: "resolved-remote-password", // pragma: allowlist secret
|
||||
},
|
||||
agentDirs: ["/tmp/openclaw-agent-main"],
|
||||
loadAuthStore: () => ({ version: 1, profiles: {} }),
|
||||
@@ -846,7 +846,7 @@ describe("secrets runtime snapshot", () => {
|
||||
},
|
||||
}),
|
||||
env: {
|
||||
REMOTE_PASSWORD: "resolved-remote-password",
|
||||
REMOTE_PASSWORD: "resolved-remote-password", // pragma: allowlist secret
|
||||
},
|
||||
agentDirs: ["/tmp/openclaw-agent-main"],
|
||||
loadAuthStore: () => ({ version: 1, profiles: {} }),
|
||||
@@ -980,8 +980,8 @@ describe("secrets runtime snapshot", () => {
|
||||
},
|
||||
}),
|
||||
env: {
|
||||
NEXTCLOUD_BOT_SECRET: "resolved-nextcloud-bot-secret",
|
||||
NEXTCLOUD_API_PASSWORD: "resolved-nextcloud-api-password",
|
||||
NEXTCLOUD_BOT_SECRET: "resolved-nextcloud-bot-secret", // pragma: allowlist secret
|
||||
NEXTCLOUD_API_PASSWORD: "resolved-nextcloud-api-password", // pragma: allowlist secret
|
||||
},
|
||||
agentDirs: ["/tmp/openclaw-agent-main"],
|
||||
loadAuthStore: () => ({ version: 1, profiles: {} }),
|
||||
@@ -1022,8 +1022,8 @@ describe("secrets runtime snapshot", () => {
|
||||
},
|
||||
}),
|
||||
env: {
|
||||
NEXTCLOUD_WORK_BOT_SECRET: "resolved-nextcloud-work-bot-secret",
|
||||
NEXTCLOUD_WORK_API_PASSWORD: "resolved-nextcloud-work-api-password",
|
||||
NEXTCLOUD_WORK_BOT_SECRET: "resolved-nextcloud-work-bot-secret", // pragma: allowlist secret
|
||||
NEXTCLOUD_WORK_API_PASSWORD: "resolved-nextcloud-work-api-password", // pragma: allowlist secret
|
||||
},
|
||||
agentDirs: ["/tmp/openclaw-agent-main"],
|
||||
loadAuthStore: () => ({ version: 1, profiles: {} }),
|
||||
@@ -1058,7 +1058,7 @@ describe("secrets runtime snapshot", () => {
|
||||
}),
|
||||
env: {
|
||||
REMOTE_GATEWAY_TOKEN: "tailscale-remote-token",
|
||||
REMOTE_GATEWAY_PASSWORD: "tailscale-remote-password",
|
||||
REMOTE_GATEWAY_PASSWORD: "tailscale-remote-password", // pragma: allowlist secret
|
||||
},
|
||||
agentDirs: ["/tmp/openclaw-agent-main"],
|
||||
loadAuthStore: () => ({ version: 1, profiles: {} }),
|
||||
@@ -1931,7 +1931,7 @@ describe("secrets runtime snapshot", () => {
|
||||
list: [{ id: "worker" }],
|
||||
},
|
||||
},
|
||||
env: { OPENAI_API_KEY: "sk-runtime-worker" },
|
||||
env: { OPENAI_API_KEY: "sk-runtime-worker" }, // pragma: allowlist secret
|
||||
});
|
||||
|
||||
await expect(fs.access(workerStorePath)).rejects.toMatchObject({ code: "ENOENT" });
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { isNonEmptyString, isRecord } from "./shared.js";
|
||||
|
||||
export type SecretExpectedResolvedValue = "string" | "string-or-object";
|
||||
export type SecretExpectedResolvedValue = "string" | "string-or-object"; // pragma: allowlist secret
|
||||
|
||||
export function isExpectedResolvedSecretValue(
|
||||
value: unknown,
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import type { SecretTargetRegistryEntry } from "./target-registry-types.js";
|
||||
|
||||
const SECRET_INPUT_SHAPE = "secret_input"; // pragma: allowlist secret
|
||||
const SIBLING_REF_SHAPE = "sibling_ref"; // pragma: allowlist secret
|
||||
|
||||
const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
{
|
||||
id: "auth-profiles.api_key.key",
|
||||
@@ -7,7 +10,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
configFile: "auth-profiles.json",
|
||||
pathPattern: "profiles.*.key",
|
||||
refPathPattern: "profiles.*.keyRef",
|
||||
secretShape: "sibling_ref",
|
||||
secretShape: SIBLING_REF_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -20,7 +23,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
configFile: "auth-profiles.json",
|
||||
pathPattern: "profiles.*.token",
|
||||
refPathPattern: "profiles.*.tokenRef",
|
||||
secretShape: "sibling_ref",
|
||||
secretShape: SIBLING_REF_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -32,7 +35,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "agents.defaults.memorySearch.remote.apiKey",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "agents.defaults.memorySearch.remote.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -43,7 +46,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "agents.list[].memorySearch.remote.apiKey",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "agents.list[].memorySearch.remote.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -54,7 +57,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.bluebubbles.accounts.*.password",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.bluebubbles.accounts.*.password",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -65,7 +68,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.bluebubbles.password",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.bluebubbles.password",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -76,7 +79,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.discord.accounts.*.pluralkit.token",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.discord.accounts.*.pluralkit.token",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -87,7 +90,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.discord.accounts.*.token",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.discord.accounts.*.token",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -98,7 +101,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.discord.accounts.*.voice.tts.elevenlabs.apiKey",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.discord.accounts.*.voice.tts.elevenlabs.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -109,7 +112,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.discord.accounts.*.voice.tts.openai.apiKey",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.discord.accounts.*.voice.tts.openai.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -120,7 +123,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.discord.pluralkit.token",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.discord.pluralkit.token",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -131,7 +134,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.discord.token",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.discord.token",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -142,7 +145,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.discord.voice.tts.elevenlabs.apiKey",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.discord.voice.tts.elevenlabs.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -153,7 +156,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.discord.voice.tts.openai.apiKey",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.discord.voice.tts.openai.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -164,7 +167,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.feishu.accounts.*.appSecret",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.feishu.accounts.*.appSecret",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -175,7 +178,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.feishu.accounts.*.verificationToken",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.feishu.accounts.*.verificationToken",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -186,7 +189,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.feishu.appSecret",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.feishu.appSecret",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -197,7 +200,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.feishu.verificationToken",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.feishu.verificationToken",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -210,7 +213,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.googlechat.accounts.*.serviceAccount",
|
||||
refPathPattern: "channels.googlechat.accounts.*.serviceAccountRef",
|
||||
secretShape: "sibling_ref",
|
||||
secretShape: SIBLING_REF_SHAPE,
|
||||
expectedResolvedValue: "string-or-object",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -223,7 +226,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.googlechat.serviceAccount",
|
||||
refPathPattern: "channels.googlechat.serviceAccountRef",
|
||||
secretShape: "sibling_ref",
|
||||
secretShape: SIBLING_REF_SHAPE,
|
||||
expectedResolvedValue: "string-or-object",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -234,7 +237,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.irc.accounts.*.nickserv.password",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.irc.accounts.*.nickserv.password",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -245,7 +248,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.irc.accounts.*.password",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.irc.accounts.*.password",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -256,7 +259,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.irc.nickserv.password",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.irc.nickserv.password",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -267,7 +270,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.irc.password",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.irc.password",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -278,7 +281,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.mattermost.accounts.*.botToken",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.mattermost.accounts.*.botToken",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -289,7 +292,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.mattermost.botToken",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.mattermost.botToken",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -300,7 +303,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.matrix.accounts.*.password",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.matrix.accounts.*.password",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -311,7 +314,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.matrix.password",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.matrix.password",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -322,7 +325,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.msteams.appPassword",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.msteams.appPassword",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -333,7 +336,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.nextcloud-talk.accounts.*.apiPassword",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.nextcloud-talk.accounts.*.apiPassword",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -344,7 +347,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.nextcloud-talk.accounts.*.botSecret",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.nextcloud-talk.accounts.*.botSecret",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -355,7 +358,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.nextcloud-talk.apiPassword",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.nextcloud-talk.apiPassword",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -366,7 +369,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.nextcloud-talk.botSecret",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.nextcloud-talk.botSecret",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -377,7 +380,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.slack.accounts.*.appToken",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.slack.accounts.*.appToken",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -388,7 +391,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.slack.accounts.*.botToken",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.slack.accounts.*.botToken",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -399,7 +402,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.slack.accounts.*.signingSecret",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.slack.accounts.*.signingSecret",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -410,7 +413,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.slack.accounts.*.userToken",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.slack.accounts.*.userToken",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -421,7 +424,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.slack.appToken",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.slack.appToken",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -432,7 +435,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.slack.botToken",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.slack.botToken",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -443,7 +446,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.slack.signingSecret",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.slack.signingSecret",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -454,7 +457,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.slack.userToken",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.slack.userToken",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -465,7 +468,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.telegram.accounts.*.botToken",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.telegram.accounts.*.botToken",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -476,7 +479,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.telegram.accounts.*.webhookSecret",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.telegram.accounts.*.webhookSecret",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -487,7 +490,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.telegram.botToken",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.telegram.botToken",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -498,7 +501,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.telegram.webhookSecret",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.telegram.webhookSecret",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -509,7 +512,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.zalo.accounts.*.botToken",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.zalo.accounts.*.botToken",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -520,7 +523,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.zalo.accounts.*.webhookSecret",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.zalo.accounts.*.webhookSecret",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -531,7 +534,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.zalo.botToken",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.zalo.botToken",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -542,7 +545,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "channels.zalo.webhookSecret",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "channels.zalo.webhookSecret",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -553,7 +556,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "cron.webhookToken",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "cron.webhookToken",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -564,7 +567,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "gateway.auth.token",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "gateway.auth.token",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -575,7 +578,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "gateway.auth.password",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "gateway.auth.password",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -586,7 +589,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "gateway.remote.password",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "gateway.remote.password",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -597,7 +600,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "gateway.remote.token",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "gateway.remote.token",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -608,7 +611,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "messages.tts.elevenlabs.apiKey",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "messages.tts.elevenlabs.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -619,7 +622,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "messages.tts.openai.apiKey",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "messages.tts.openai.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -631,7 +634,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetTypeAliases: ["models.providers.*.apiKey"],
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "models.providers.*.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -645,7 +648,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetTypeAliases: ["skills.entries.*.apiKey"],
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "skills.entries.*.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -656,7 +659,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "talk.apiKey",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "talk.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -667,7 +670,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "talk.providers.*.apiKey",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "talk.providers.*.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -678,7 +681,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "tools.web.search.apiKey",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "tools.web.search.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -689,7 +692,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "tools.web.search.gemini.apiKey",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "tools.web.search.gemini.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -700,7 +703,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "tools.web.search.grok.apiKey",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "tools.web.search.grok.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -711,7 +714,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "tools.web.search.kimi.apiKey",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "tools.web.search.kimi.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
@@ -722,7 +725,7 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
targetType: "tools.web.search.perplexity.apiKey",
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "tools.web.search.perplexity.apiKey",
|
||||
secretShape: "secret_input",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
|
||||
@@ -49,8 +49,8 @@ describe("target registry pattern helpers", () => {
|
||||
},
|
||||
talk: {
|
||||
providers: {
|
||||
openai: { apiKey: "oa" },
|
||||
anthropic: { apiKey: "an" },
|
||||
openai: { apiKey: "oa" }, // pragma: allowlist secret
|
||||
anthropic: { apiKey: "an" }, // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -47,7 +47,8 @@ export function compileTargetRegistryEntry(
|
||||
const pathDynamicTokenCount = countDynamicPatternTokens(pathTokens);
|
||||
const refPathTokens = entry.refPathPattern ? parsePathPattern(entry.refPathPattern) : undefined;
|
||||
const refPathDynamicTokenCount = refPathTokens ? countDynamicPatternTokens(refPathTokens) : 0;
|
||||
if (entry.secretShape === "sibling_ref" && !refPathTokens) {
|
||||
const requiresSiblingRefPath = entry.secretShape === "sibling_ref"; // pragma: allowlist secret
|
||||
if (requiresSiblingRefPath && !refPathTokens) {
|
||||
throw new Error(`Missing refPathPattern for sibling_ref target: ${entry.id}`);
|
||||
}
|
||||
if (refPathTokens && refPathDynamicTokenCount !== pathDynamicTokenCount) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export type SecretTargetConfigFile = "openclaw.json" | "auth-profiles.json";
|
||||
export type SecretTargetShape = "secret_input" | "sibling_ref";
|
||||
export type SecretTargetExpected = "string" | "string-or-object";
|
||||
export type SecretTargetConfigFile = "openclaw.json" | "auth-profiles.json"; // pragma: allowlist secret
|
||||
export type SecretTargetShape = "secret_input" | "sibling_ref"; // pragma: allowlist secret
|
||||
export type SecretTargetExpected = "string" | "string-or-object"; // pragma: allowlist secret
|
||||
export type AuthProfileType = "api_key" | "token";
|
||||
|
||||
export type SecretTargetRegistryEntry = {
|
||||
|
||||
@@ -118,7 +118,7 @@ describe("resolveGatewayConnection", () => {
|
||||
gateway: {
|
||||
mode: "local",
|
||||
auth: {
|
||||
password: "config-password",
|
||||
password: "config-password", // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -134,7 +134,7 @@ describe("resolveGatewayConnection", () => {
|
||||
mode: "local",
|
||||
auth: {
|
||||
token: "config-token",
|
||||
password: "config-password",
|
||||
password: "config-password", // pragma: allowlist secret
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -180,13 +180,15 @@ describe("resolveGatewayConnection", () => {
|
||||
loadConfig.mockReturnValue({
|
||||
gateway: {
|
||||
mode: "remote",
|
||||
remote: { url: "wss://remote.example/ws", token: "remote-token", password: "remote-pass" },
|
||||
remote: { url: "wss://remote.example/ws", token: "remote-token", password: "remote-pass" }, // pragma: allowlist secret
|
||||
},
|
||||
});
|
||||
|
||||
await withEnvAsync({ OPENCLAW_GATEWAY_PASSWORD: "env-pass" }, async () => {
|
||||
const gatewayPasswordEnv = "OPENCLAW_GATEWAY_PASSWORD"; // pragma: allowlist secret
|
||||
const gatewayPassword = "env-pass"; // pragma: allowlist secret
|
||||
await withEnvAsync({ [gatewayPasswordEnv]: gatewayPassword }, async () => {
|
||||
const result = await resolveGatewayConnection({});
|
||||
expect(result.password).toBe("env-pass");
|
||||
expect(result.password).toBe(gatewayPassword);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -263,12 +265,12 @@ describe("resolveGatewayConnection", () => {
|
||||
const tokenExecProgram = [
|
||||
"const fs=require('node:fs');",
|
||||
`fs.writeFileSync(${JSON.stringify(tokenMarker)},'1');`,
|
||||
"process.stdout.write(JSON.stringify({ protocolVersion: 1, values: { TOKEN_SECRET: 'token-from-exec' } }));",
|
||||
"process.stdout.write(JSON.stringify({ protocolVersion: 1, values: { TOKEN_SECRET: 'token-from-exec' } }));", // pragma: allowlist secret
|
||||
].join("");
|
||||
const passwordExecProgram = [
|
||||
"const fs=require('node:fs');",
|
||||
`fs.writeFileSync(${JSON.stringify(passwordMarker)},'1');`,
|
||||
"process.stdout.write(JSON.stringify({ protocolVersion: 1, values: { PASSWORD_SECRET: 'password-from-exec' } }));",
|
||||
"process.stdout.write(JSON.stringify({ protocolVersion: 1, values: { PASSWORD_SECRET: 'password-from-exec' } }));", // pragma: allowlist secret
|
||||
].join("");
|
||||
|
||||
loadConfig.mockReturnValue({
|
||||
@@ -316,12 +318,12 @@ describe("resolveGatewayConnection", () => {
|
||||
const tokenExecProgram = [
|
||||
"const fs=require('node:fs');",
|
||||
`fs.writeFileSync(${JSON.stringify(tokenMarker)},'1');`,
|
||||
"process.stdout.write(JSON.stringify({ protocolVersion: 1, values: { TOKEN_SECRET: 'token-from-exec' } }));",
|
||||
"process.stdout.write(JSON.stringify({ protocolVersion: 1, values: { TOKEN_SECRET: 'token-from-exec' } }));", // pragma: allowlist secret
|
||||
].join("");
|
||||
const passwordExecProgram = [
|
||||
"const fs=require('node:fs');",
|
||||
`fs.writeFileSync(${JSON.stringify(passwordMarker)},'1');`,
|
||||
"process.stdout.write(JSON.stringify({ protocolVersion: 1, values: { PASSWORD_SECRET: 'password-from-exec' } }));",
|
||||
"process.stdout.write(JSON.stringify({ protocolVersion: 1, values: { PASSWORD_SECRET: 'password-from-exec' } }));", // pragma: allowlist secret
|
||||
].join("");
|
||||
|
||||
loadConfig.mockReturnValue({
|
||||
|
||||
@@ -250,14 +250,14 @@ describe("sanitizeRenderableText", () => {
|
||||
});
|
||||
|
||||
it("preserves long credential-like mixed alnum tokens for copy safety", () => {
|
||||
const input = "e3b19c3b87bcf364b23eebb2c276e96ec478956ba1d84c93";
|
||||
const input = "e3b19c3b87bcf364b23eebb2c276e96ec478956ba1d84c93"; // pragma: allowlist secret
|
||||
const sanitized = sanitizeRenderableText(input);
|
||||
|
||||
expect(sanitized).toBe(input);
|
||||
});
|
||||
|
||||
it("preserves quoted credential-like mixed alnum tokens for copy safety", () => {
|
||||
const input = "'e3b19c3b87bcf364b23eebb2c276e96ec478956ba1d84c93'";
|
||||
const input = "'e3b19c3b87bcf364b23eebb2c276e96ec478956ba1d84c93'"; // pragma: allowlist secret
|
||||
const sanitized = sanitizeRenderableText(input);
|
||||
|
||||
expect(sanitized).toBe(input);
|
||||
|
||||
@@ -15,6 +15,6 @@ describe("maskApiKey", () => {
|
||||
});
|
||||
|
||||
it("masks long values with first and last 8 chars", () => {
|
||||
expect(maskApiKey("1234567890abcdefghijklmnop")).toBe("12345678...ijklmnop");
|
||||
expect(maskApiKey("1234567890abcdefghijklmnop")).toBe("12345678...ijklmnop"); // pragma: allowlist secret
|
||||
});
|
||||
});
|
||||
|
||||
@@ -113,7 +113,7 @@ describe("finalizeOnboardingWizard", () => {
|
||||
|
||||
it("resolves gateway password SecretRef for probe and TUI", async () => {
|
||||
const previous = process.env.OPENCLAW_GATEWAY_PASSWORD;
|
||||
process.env.OPENCLAW_GATEWAY_PASSWORD = "resolved-gateway-password";
|
||||
process.env.OPENCLAW_GATEWAY_PASSWORD = "resolved-gateway-password"; // pragma: allowlist secret
|
||||
const select = vi.fn(async (params: { message: string }) => {
|
||||
if (params.message === "How do you want to hatch your bot?") {
|
||||
return "tui";
|
||||
@@ -179,13 +179,13 @@ describe("finalizeOnboardingWizard", () => {
|
||||
expect(probeGatewayReachable).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
url: "ws://127.0.0.1:18789",
|
||||
password: "resolved-gateway-password",
|
||||
password: "resolved-gateway-password", // pragma: allowlist secret
|
||||
}),
|
||||
);
|
||||
expect(runTui).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
url: "ws://127.0.0.1:18789",
|
||||
password: "resolved-gateway-password",
|
||||
password: "resolved-gateway-password", // pragma: allowlist secret
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -165,7 +165,7 @@ export async function configureGatewayForOnboarding(
|
||||
defaults: nextConfig.secrets?.defaults,
|
||||
}).ref;
|
||||
const tokenMode =
|
||||
flow === "quickstart" && opts.secretInputMode !== "ref"
|
||||
flow === "quickstart" && opts.secretInputMode !== "ref" // pragma: allowlist secret
|
||||
? quickstartTokenRef
|
||||
? "ref"
|
||||
: "plaintext"
|
||||
|
||||
@@ -58,7 +58,7 @@ export const de: TranslationMap = {
|
||||
subtitle: "Wo sich das Dashboard verbindet und wie es sich authentifiziert.",
|
||||
wsUrl: "WebSocket-URL",
|
||||
token: "Gateway-Token",
|
||||
password: "Passwort (nicht gespeichert)",
|
||||
password: "Passwort (nicht gespeichert)", // pragma: allowlist secret
|
||||
sessionKey: "Standard-Sitzungsschlüssel",
|
||||
language: "Sprache",
|
||||
connectHint: "Klicken Sie auf Verbinden, um Verbindungsänderungen anzuwenden.",
|
||||
|
||||
@@ -58,7 +58,7 @@ export const es: TranslationMap = {
|
||||
subtitle: "Dónde se conecta el panel y cómo se autentica.",
|
||||
wsUrl: "URL de WebSocket",
|
||||
token: "Token de la puerta de enlace",
|
||||
password: "Contraseña (no se guarda)",
|
||||
password: "Contraseña (no se guarda)", // pragma: allowlist secret
|
||||
sessionKey: "Clave de sesión predeterminada",
|
||||
language: "Idioma",
|
||||
connectHint: "Haz clic en Conectar para aplicar los cambios de conexión.",
|
||||
|
||||
Reference in New Issue
Block a user