fix: clean detached auth profile secrets

This commit is contained in:
Peter Steinberger
2026-05-16 05:50:23 +01:00
parent cfdac077b4
commit a142590331

View File

@@ -1,3 +1,4 @@
import { createHash } from "node:crypto";
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
@@ -77,6 +78,17 @@ function readRawPersistedAuthProfiles(agentDir?: string): {
};
}
function resolveExpectedOAuthProfileSecretPath(
agentDir: string | undefined,
profileId: string,
): string {
const id = createHash("sha256")
.update(`${authProfileStoreKey(agentDir)}\0${profileId}`)
.digest("hex")
.slice(0, 32);
return path.join(resolveOAuthDir(), "auth-profiles", `${id}.json`);
}
describe("saveAuthProfileStore", () => {
let stateRoot = "";
@@ -353,6 +365,36 @@ describe("saveAuthProfileStore", () => {
}
});
it("removes detached OAuth secret files when profiles are deleted", async () => {
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-auth-save-secret-"));
const profileId = "openai-codex:default";
try {
saveAuthProfileStore(
{
version: 1,
profiles: {
[profileId]: {
type: "oauth",
provider: "openai-codex",
access: "access-token",
refresh: "refresh-token",
expires: Date.now() + 60_000,
},
},
},
agentDir,
);
const secretPath = resolveExpectedOAuthProfileSecretPath(agentDir, profileId);
await expect(fs.stat(secretPath)).resolves.toBeTruthy();
saveAuthProfileStore({ version: 1, profiles: {} }, agentDir);
await expect(fs.stat(secretPath)).rejects.toMatchObject({ code: "ENOENT" });
} finally {
await fs.rm(agentDir, { recursive: true, force: true });
}
});
it("writes runtime scheduling state to SQLite only", async () => {
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-auth-save-state-"));
try {