11import { describe , expect , test } from "bun:test"
2- import { Telemetry } from "../../src/altimate/telemetry"
32import { ErrorDetail } from "../../src/altimate/telemetry/error-detail"
43
5- const { buildErrorFingerprintEvent, describeToolError, templateErrorMessage, ERROR_VOCABULARY } = ErrorDetail
6-
7- const CREDENTIAL_WORDS = [
8- "password" ,
9- "passwd" ,
10- "pwd" ,
11- "secret" ,
12- "token" ,
13- "key" ,
14- "auth" ,
15- "authorization" ,
16- "credential" ,
17- "credentials" ,
18- "bearer" ,
19- "cookie" ,
20- "session" ,
21- "passphrase" ,
22- ]
4+ const { buildErrorFingerprintEvent, describeToolError, templateErrorMessage, ERROR_VOCABULARY , CREDENTIAL_WORDS } =
5+ ErrorDetail
236
247describe ( "templateErrorMessage" , ( ) => {
258 test . each ( [
@@ -31,7 +14,7 @@ describe("templateErrorMessage", () => {
3114 expect ( templateErrorMessage ( raw ) ) . toBe ( expected )
3215 } )
3316
34- test . each ( CREDENTIAL_WORDS ) ( "masks vocabulary words after %s" , ( word ) => {
17+ test . each ( [ ... CREDENTIAL_WORDS ] ) ( "masks vocabulary words after %s" , ( word ) => {
3518 expect ( templateErrorMessage ( `request failed with ${ word } : connection refused` ) ) . toBe ( "request failed with <x>" )
3619 } )
3720
@@ -55,6 +38,70 @@ describe("templateErrorMessage", () => {
5538 )
5639 } )
5740
41+ test . each ( [
42+ "apikey" ,
43+ "apiKey" ,
44+ "accessToken" ,
45+ "authToken" ,
46+ "refreshToken" ,
47+ "bearerToken" ,
48+ "jwtToken" ,
49+ "jwtSecret" ,
50+ "clientSecret" ,
51+ "appSecret" ,
52+ "signature" ,
53+ "sig" ,
54+ "pass" ,
55+ "passwords" ,
56+ "secretKey" ,
57+ "sessionId" ,
58+ "connectionString" ,
59+ ] ) ( "masks the exact credential alias %s" , ( key ) => {
60+ expect ( templateErrorMessage ( `request failed: ${ key } =wrong user` ) ) . toBe ( "request failed <x>" )
61+ expect ( templateErrorMessage ( `${ key } : connection refused` ) ) . toBe ( "<x>" )
62+ } )
63+
64+ test . each ( [
65+ "request failed: connection_string=wrong user" ,
66+ "request failed: CONNECTION_STRING: connection refused" ,
67+ 'request failed: "connection_string": "wrong user"' ,
68+ "request failed: connection-string=wrong user" ,
69+ "request failed: connection_\x1b[31mstring=wrong user" ,
70+ ] ) ( "masks the exact connection string key: %j" , ( raw ) => {
71+ expect ( templateErrorMessage ( raw ) ) . toBe ( "request failed <x>" )
72+ } )
73+
74+ test . each ( [
75+ [ "connection string is invalid" , "connection string is invalid" ] ,
76+ [ "connection refused" , "connection refused" ] ,
77+ [ "signal received" , "signal received" ] ,
78+ [ "connection_stringify is invalid" , "connection <x> is invalid" ] ,
79+ [ "disconnection_string is invalid" , "<x> string is invalid" ] ,
80+ [ "connection_strings are invalid" , "connection <x> are invalid" ] ,
81+ [ "apikeyboard sigil signatured tokenizer failed" , "<x> failed" ] ,
82+ ] ) ( "keeps diagnostics without an exact credential marker: %s" , ( raw , expected ) => {
83+ expect ( templateErrorMessage ( raw ) ) . toBe ( expected )
84+ } )
85+
86+ test . each ( [
87+ "request failed: \x1b[31mpassword\x1b[0m=wrong user" ,
88+ "request failed: pass\x1b[31mword=wrong user" ,
89+ "request failed: api\x1b[31mKey=wrong user" ,
90+ "request failed: \x1b[1;31mpassword\x1b[0m=connection refused" ,
91+ "request failed: \x1b]8;;https://example.test\x07password\x1b]8;;\x07=wrong user" ,
92+ "request failed: \x9b31mpassword\x9b0m=wrong user" ,
93+ ] ) ( "ignores ANSI sequences when matching credentials: %j" , ( raw ) => {
94+ expect ( templateErrorMessage ( raw ) ) . toBe ( "request failed <x>" )
95+ } )
96+
97+ test ( "keeps diagnostic words inside ANSI styling" , ( ) => {
98+ expect ( templateErrorMessage ( "connection \x1b[31mrefused\x1b[0m" ) ) . toBe ( "connection refused" )
99+ } )
100+
101+ test . each ( [ "\n" , "\r" , "\r\n" , "\u2028" , "\u2029" ] ) ( "does not let an OSC sequence consume %j" , ( newline ) => {
102+ expect ( templateErrorMessage ( `first line \x1b]8;;${ newline } \x07wrong user` ) ) . toBe ( "first line" )
103+ } )
104+
58105 const adversarial = [
59106 "password: hunter" ,
60107 "password: supersecret" ,
@@ -86,7 +133,7 @@ describe("templateErrorMessage", () => {
86133 expect ( tok === "<x>" || ERROR_VOCABULARY . has ( tok ) ) . toBe ( true )
87134 }
88135 expect ( out ) . not . toContain ( "<x> <x>" )
89- for ( const w of CREDENTIAL_WORDS ) expect ( out ) . not . toContain ( w )
136+ for ( const w of CREDENTIAL_WORDS ) expect ( out . split ( " " ) ) . not . toContain ( w )
90137 } )
91138
92139 test ( "user words never survive" , ( ) => {
@@ -137,8 +184,10 @@ describe("error_fingerprint wiring", () => {
137184 expect ( "stack" in ev ) . toBe ( false )
138185 } )
139186
140- test ( "credential suffix is hidden in the event without changing the hash" , ( ) => {
141- const raw = "request failed: password is connection refused"
187+ test . each ( [
188+ "request failed: password is connection refused" ,
189+ "request failed: \x1b[31mpassword\x1b[0m is connection refused" ,
190+ ] ) ( "credential suffix is hidden in the event without changing the hash: %j" , ( raw ) => {
142191 const detail = describeToolError ( raw )
143192 const event = buildErrorFingerprintEvent ( "s1" , {
144193 ...detail ,
@@ -150,7 +199,7 @@ describe("error_fingerprint wiring", () => {
150199 } )
151200 expect ( event ) . toMatchObject ( {
152201 error_message : "request failed <x>" ,
153- error_hash : Telemetry . hashError ( Telemetry . maskString ( raw ) . slice ( 0 , 500 ) ) ,
202+ error_hash : "ae7e754cfb2d72a2" ,
154203 } )
155204 } )
156205
0 commit comments