From d1c054e6fd3a1c6b914f96d6c4e6d08a5dd853de Mon Sep 17 00:00:00 2001 From: Dotta Date: Sat, 24 Oct 2026 13:37:50 -0700 Subject: [PATCH] Reject prototype-like keys in eval trace headers Co-Authored-By: Paperclip --- packages/paperclip-runner/src/cli/eval-gateway-runtime.test.ts | 3 ++- .../paperclip-runner/src/cli/eval-observability-runtime.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/paperclip-runner/src/cli/eval-gateway-runtime.test.ts b/packages/paperclip-runner/src/cli/eval-gateway-runtime.test.ts index 9e468c9f484..d4e889ecf32 100644 --- a/packages/paperclip-runner/src/cli/eval-gateway-runtime.test.ts +++ b/packages/paperclip-runner/src/cli/eval-gateway-runtime.test.ts @@ -91,12 +91,13 @@ it.each([["codex", undefined], ["acpx", "claude"]])("applies the existing %s/%s } finally { await gateway.close(); } }); -it.each(["identity", "endpoint", "parent", "credential", "company", "rawBodies", "modelEnvironment", "extraField", "unknownExporter"])("rejects observability %s drift before changing the gateway home", async fault => { +it.each(["identity", "endpoint", "parent", "credential", "company", "rawBodies", "modelEnvironment", "extraField", "unknownExporter", "prototypeHeader"])("rejects observability %s drift before changing the gateway home", async fault => { const f = await fixture(), observation = await observabilityFixture(f); const descriptor = observation.descriptor as unknown as Record; if (fault === "identity") descriptor.attemptId = "other"; if (fault === "endpoint") descriptor.launch.otelConfig.exporter["otlp-http"].endpoint = "https://api.braintrust.dev/otel/v1/logs"; if (fault === "parent") descriptor.traceId = "3".repeat(32); + if (fault === "prototypeHeader") descriptor.launch.environment.OTEL_EXPORTER_OTLP_LOGS_HEADERS += ",__proto__=ignored"; if (fault === "credential") descriptor.launch.environment.OTEL_EXPORTER_OTLP_LOGS_HEADERS += ",authorization=Bearer%20upstream-secret"; if (fault === "company") descriptor.launch.otelConfig.span_attributes["paperclip.company.id"] = "other"; if (fault === "rawBodies") descriptor.launch.otelConfig.log_guardian_assessments = true; diff --git a/packages/paperclip-runner/src/cli/eval-observability-runtime.ts b/packages/paperclip-runner/src/cli/eval-observability-runtime.ts index 5bbe66b82d3..00e8b23a8b4 100644 --- a/packages/paperclip-runner/src/cli/eval-observability-runtime.ts +++ b/packages/paperclip-runner/src/cli/eval-observability-runtime.ts @@ -22,7 +22,7 @@ function text(value: unknown): string { return value; } function decodedMap(value: unknown): Record { - const result: Record = {}; + const result: Record = Object.create(null); for (const item of text(value).split(",")) { const index = item.indexOf("="); if (index < 1) throw invalid();