Skip to content

Commit 5a1d68d

Browse files
committed
fix(claude): allowlist public string errors
1 parent 20e2d93 commit 5a1d68d

2 files changed

Lines changed: 13 additions & 10 deletions

File tree

src/provider.test.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,16 +1064,18 @@ describe("Claude provider helpers", () => {
10641064
throw new Error("expected Claude provider failure");
10651065
});
10661066

1067-
it("does not preview arbitrary string Claude errors", () => {
1068-
try {
1069-
extractClaudeStructuredOutput(JSON.stringify({ error: "SOURCE CONTEXT SECRET" }));
1070-
} catch (err) {
1071-
expect(err).toBeInstanceOf(ClawpatchError);
1072-
expect((err as ClawpatchError).message).toBe("claude provider error: provider-error");
1073-
expect((err as ClawpatchError).message).not.toContain("SOURCE CONTEXT SECRET");
1074-
return;
1067+
it("does not preview arbitrary or token-shaped string Claude errors", () => {
1068+
for (const secret of ["SOURCE CONTEXT SECRET", "sk-ant-secret-shaped-value"]) {
1069+
try {
1070+
extractClaudeStructuredOutput(JSON.stringify({ error: secret }));
1071+
} catch (err) {
1072+
expect(err).toBeInstanceOf(ClawpatchError);
1073+
expect((err as ClawpatchError).message).toBe("claude provider error: provider-error");
1074+
expect((err as ClawpatchError).message).not.toContain(secret);
1075+
continue;
1076+
}
1077+
throw new Error("expected Claude provider failure");
10751078
}
1076-
throw new Error("expected Claude provider failure");
10771079
});
10781080

10791081
it("does not include stdout or prompt previews in Claude failure messages", () => {

src/providers/claude.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const CLAUDE_DEFAULT_TIMEOUT_MS = 180_000;
2828
const CLAUDE_READ_ONLY_TOOLS = "Read,Grep,Glob";
2929
const CLAUDE_WRITE_TOOLS = "default";
3030
const CLAUDE_SAFE_MODE_MIN_VERSION: [number, number, number] = [2, 1, 169];
31+
const CLAUDE_PUBLIC_STRING_ERROR_CODES = new Set(["authentication_failed"]);
3132
const CLAUDE_AUTH_SMOKE_SCHEMA = {
3233
type: "object",
3334
properties: { ok: { type: "boolean", const: true } },
@@ -373,7 +374,7 @@ function claudeStructuredOutput(value: unknown): { found: boolean; value: unknow
373374
function claudeEnvelopeErrorCode(error: unknown): string | null {
374375
if (typeof error === "string") {
375376
const trimmed = error.trim();
376-
return /^[a-z][a-z0-9_.:-]{0,79}$/iu.test(trimmed) ? safeProviderPreview(trimmed) : null;
377+
return CLAUDE_PUBLIC_STRING_ERROR_CODES.has(trimmed) ? trimmed : null;
377378
}
378379
if (typeof error !== "object" || error === null) {
379380
return null;

0 commit comments

Comments
 (0)