
























@@ -5,7 +5,7 @@ import { describe, expect, it, vi } from "vitest";
55import { resolveOAuthDir } from "../../config/paths.js";
66import { AUTH_STORE_VERSION } from "./constants.js";
77import { resolveAuthStorePath } from "./paths.js";
8-import { promoteAuthProfileInOrder } from "./profiles.js";
8+import { promoteAuthProfileInOrder, upsertAuthProfileWithLock } from "./profiles.js";
99import {
1010clearRuntimeAuthProfileStoreSnapshots,
1111findPersistedAuthProfileCredential,
@@ -138,6 +138,54 @@ function expectOpenClawCredentialsOAuthRef(
138138}
139139140140describe("promoteAuthProfileInOrder", () => {
141+it("normalizes copied secrets when using the locked upsert path", async () => {
142+const stateDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-auth-profile-upsert-"));
143+const agentDir = path.join(stateDir, "agents", "main", "agent");
144+const previousStateDir = process.env.OPENCLAW_STATE_DIR;
145+process.env.OPENCLAW_STATE_DIR = stateDir;
146+try {
147+fs.mkdirSync(agentDir, { recursive: true });
148+149+await upsertAuthProfileWithLock({
150+profileId: "openai:manual",
151+credential: {
152+type: "token",
153+provider: "openai",
154+token: " bearer\r\n-token\u2502 ",
155+},
156+ agentDir,
157+});
158+await upsertAuthProfileWithLock({
159+profileId: "anthropic:key",
160+credential: {
161+type: "api_key",
162+provider: "anthropic",
163+key: " sk-\r\nant\u2502 ",
164+},
165+ agentDir,
166+});
167+168+const profiles = loadAuthProfileStoreWithoutExternalProfiles(agentDir).profiles;
169+expect(profiles["openai:manual"]).toMatchObject({
170+type: "token",
171+provider: "openai",
172+token: "bearer-token",
173+});
174+expect(profiles["anthropic:key"]).toMatchObject({
175+type: "api_key",
176+provider: "anthropic",
177+key: "sk-ant",
178+});
179+} finally {
180+if (previousStateDir === undefined) {
181+delete process.env.OPENCLAW_STATE_DIR;
182+} else {
183+process.env.OPENCLAW_STATE_DIR = previousStateDir;
184+}
185+fs.rmSync(stateDir, { recursive: true, force: true });
186+}
187+});
188+141189it("omits inline openai-codex oauth secrets from persisted auth profile files", () => {
142190const stateDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-auth-profile-metadata-"));
143191const agentDir = path.join(stateDir, "agents", "main", "agent");
@@ -610,10 +658,18 @@ describe("promoteAuthProfileInOrder", () => {
610658{ filterExternalAuthProfiles: false },
611659);
612660661+const expectedKeyPath =
662+process.platform === "darwin"
663+ ? path.join(
664+homeDir,
665+"Library",
666+"Application Support",
667+"OpenClaw",
668+"auth-profile-secret-key",
669+)
670+ : path.join(homeDir, ".openclaw-auth-profile-secrets", "auth-profile-secret-key");
613671const keyPaths = findFilesNamed(rootDir, "auth-profile-secret-key");
614-expect(keyPaths).toEqual([
615-path.join(homeDir, ".openclaw-auth-profile-secrets", "auth-profile-secret-key"),
616-]);
672+expect(keyPaths).toEqual([expectedKeyPath]);
617673expect(keyPaths.every((keyPath) => !isPathInsideOrEqual(stateDir, keyPath))).toBe(true);
618674const keyValues = keyPaths.map((keyPath) => fs.readFileSync(keyPath, "utf8").trim());
619675const persistedStateTree = readPersistedTree(stateDir);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。