fix(secrets): explicitly pass BWS_SERVER_URL to resolver for self-hosted instances (#93929)

Merged via squash after the required `scripts/pr merge-run` workflow falsely flagged a non-overlapping mainline refactor as an overlap.

Prepared head SHA: dc0bba965a
Co-authored-by: Pandah97 <80405497+Pandah97@users.noreply.github.com>
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
Reviewed-by: @vincentkoc
This commit is contained in:
huangjianxiong
2026-06-17 22:04:48 +08:00
committed by GitHub
parent e7aa2a66f2
commit 73df6d48af
3 changed files with 63 additions and 1 deletions

View File

@@ -335,6 +335,8 @@ the config fields that accept SecretRefs.
- `BWS_ACCESS_TOKEN` available to the Gateway service.
- `PATH` passed to the resolver, or `BWS_BIN` set to the absolute `bws`
binary path.
- `BWS_SERVER_URL` must be set in the environment when using a self-hosted
Bitwarden instance.
```json5
{
@@ -343,7 +345,7 @@ the config fields that accept SecretRefs.
bws: {
source: "exec",
command: "/usr/local/bin/openclaw-bws-resolver.mjs",
passEnv: ["BWS_ACCESS_TOKEN", "PATH", "BWS_BIN"],
passEnv: ["BWS_ACCESS_TOKEN", "BWS_SERVER_URL", "PATH", "BWS_BIN"],
jsonOnly: true,
},
},

View File

@@ -51,6 +51,7 @@ const main = async () => {
encoding: "utf8",
env: {
BWS_ACCESS_TOKEN: process.env.BWS_ACCESS_TOKEN,
BWS_SERVER_URL: process.env.BWS_SERVER_URL,
PATH: process.env.PATH || "",
},
maxBuffer: 1024 * 1024,

View File

@@ -0,0 +1,59 @@
import { spawnSync } from "node:child_process";
import { chmodSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
const tempDirs: string[] = [];
const resolverPath = path.resolve("scripts/secrets/openclaw-bws-resolver.mjs");
function makeTempDir(): string {
const dir = mkdtempSync(path.join(tmpdir(), "openclaw-bws-resolver-"));
tempDirs.push(dir);
return dir;
}
afterEach(() => {
for (const dir of tempDirs.splice(0)) {
rmSync(dir, { force: true, recursive: true });
}
});
describe("openclaw-bws-resolver", () => {
it("forwards the self-hosted server URL without inheriting unrelated variables", () => {
const dir = makeTempDir();
const fakeBwsPath = path.join(dir, "bws");
writeFileSync(
fakeBwsPath,
[
"#!/usr/bin/env node",
'if (process.env.BWS_ACCESS_TOKEN !== "test-token") process.exit(10);',
'if (process.env.BWS_SERVER_URL !== "https://bws.example.test") process.exit(11);',
"if (process.env.UNRELATED_PARENT_VALUE !== undefined) process.exit(12);",
'process.stdout.write(JSON.stringify([{ key: "example", value: "resolved" }]));',
].join("\n"),
{ mode: 0o755 },
);
chmodSync(fakeBwsPath, 0o755);
const result = spawnSync(process.execPath, [resolverPath], {
encoding: "utf8",
env: {
BWS_ACCESS_TOKEN: "test-token",
BWS_BIN: fakeBwsPath,
BWS_SERVER_URL: "https://bws.example.test",
PATH: process.env.PATH ?? "",
UNRELATED_PARENT_VALUE: "do-not-forward",
},
input: JSON.stringify({ protocolVersion: 1, ids: ["example"] }),
});
expect(result.status).toBe(0);
expect(result.stderr).toBe("");
expect(JSON.parse(result.stdout)).toEqual({
protocolVersion: 1,
values: { example: "resolved" },
errors: {},
});
});
});