@@ -28,6 +28,8 @@ function cfg(mode: "tools" | "off", patterns?: string[]): OpenClawConfig {
2828}
2929
3030const EMAIL_PATTERN = String . raw `([\w]|[-.])+@([\w]|[-.])+\.\w+` ;
31+ const CIPHERTEXT_WITH_TOKEN_SHAPED_BYTES =
32+ "gAAAAABpQnQrXzzZqcAfo3unbAY-ku84xgsvB0fpLkbDvSh3WS5qzfSCmcgwr8_abcdefghijvK2RyV2GQ4ohzcfYwhRwTvY76TvR7Tvr_" ;
3133
3234describe ( "redactTranscriptMessage" , ( ) => {
3335 it ( "redacts text block matching default patterns (sk- token)" , ( ) => {
@@ -50,6 +52,75 @@ describe("redactTranscriptMessage", () => {
5052 expect ( block . thinking ) . not . toContain ( "sk-abcdef1234567890xyz" ) ;
5153 } ) ;
5254
55+ it ( "preserves OpenAI encrypted reasoning inside thinkingSignature" , ( ) => {
56+ const thinkingSignature = JSON . stringify ( {
57+ type : "reasoning" ,
58+ encrypted_content : CIPHERTEXT_WITH_TOKEN_SHAPED_BYTES ,
59+ summary : [ ] ,
60+ } ) ;
61+ const msg = {
62+ role : "assistant" ,
63+ content : [
64+ {
65+ type : "thinking" ,
66+ thinking : "secret sk-abcdef1234567890xyz" ,
67+ thinkingSignature,
68+ } ,
69+ ] ,
70+ } as unknown as AgentMessage ;
71+
72+ const result = redactTranscriptMessage ( msg , cfg ( "tools" ) ) ;
73+ const block = ( msgContent ( result ) as Array < { thinking : string ; thinkingSignature : string } > ) [ 0 ] ;
74+ expect ( block . thinking ) . not . toContain ( "sk-abcdef1234567890xyz" ) ;
75+ expect ( block . thinkingSignature ) . toBe ( thinkingSignature ) ;
76+ expect ( block . thinkingSignature ) . toContain ( CIPHERTEXT_WITH_TOKEN_SHAPED_BYTES ) ;
77+ expect ( block . thinkingSignature ) . not . toContain ( "…" ) ;
78+ } ) ;
79+
80+ it ( "preserves opaque encrypted_content fields while redacting siblings" , ( ) => {
81+ const msg = {
82+ role : "assistant" ,
83+ content : [
84+ {
85+ type : "gatewayCustom" ,
86+ encrypted_content : CIPHERTEXT_WITH_TOKEN_SHAPED_BYTES ,
87+ payload : {
88+ apiKey : "plainsecretvalue123" ,
89+ } ,
90+ } ,
91+ ] ,
92+ } as unknown as AgentMessage ;
93+
94+ const result = redactTranscriptMessage ( msg , cfg ( "tools" ) ) ;
95+ const block = (
96+ msgContent ( result ) as Array < { encrypted_content : string ; payload : { apiKey : string } } >
97+ ) [ 0 ] ;
98+ expect ( block . encrypted_content ) . toBe ( CIPHERTEXT_WITH_TOKEN_SHAPED_BYTES ) ;
99+ expect ( block . payload . apiKey ) . toBe ( "plains…e123" ) ;
100+ } ) ;
101+
102+ it ( "preserves Anthropic redacted_thinking data while redacting siblings" , ( ) => {
103+ const msg = {
104+ role : "assistant" ,
105+ content : [
106+ {
107+ type : "redacted_thinking" ,
108+ data : CIPHERTEXT_WITH_TOKEN_SHAPED_BYTES ,
109+ metadata : {
110+ accessToken : "nestedplainsecret123" ,
111+ } ,
112+ } ,
113+ ] ,
114+ } as unknown as AgentMessage ;
115+
116+ const result = redactTranscriptMessage ( msg , cfg ( "tools" ) ) ;
117+ const block = (
118+ msgContent ( result ) as Array < { data : string ; metadata : { accessToken : string } } >
119+ ) [ 0 ] ;
120+ expect ( block . data ) . toBe ( CIPHERTEXT_WITH_TOKEN_SHAPED_BYTES ) ;
121+ expect ( block . metadata . accessToken ) . toBe ( "nested…t123" ) ;
122+ } ) ;
123+
53124 it ( "redacts partialJson block" , ( ) => {
54125 const msg = {
55126 role : "assistant" ,
0 commit comments