File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -1316,6 +1316,31 @@ describe("runFromActionCache hardening", () => {
13161316 expect ( replay . steps [ 0 ] ?. message ) . toContain ( "[truncated" ) ;
13171317 } ) ;
13181318
1319+ it ( "sanitizes control characters in cached-step read diagnostics" , async ( ) => {
1320+ const agent = new HyperAgent ( {
1321+ llm : createMockLLM ( ) ,
1322+ cdpActions : false ,
1323+ } ) ;
1324+ const page = { } as import ( "@/types/agent/types" ) . HyperPage ;
1325+ const cache = {
1326+ taskId : "cache-task" ,
1327+ createdAt : new Date ( ) . toISOString ( ) ,
1328+ status : TaskStatus . COMPLETED ,
1329+ get steps ( ) : unknown [ ] {
1330+ throw new Error ( `steps\u0000\n${ "x" . repeat ( 2_000 ) } ` ) ;
1331+ } ,
1332+ } as unknown as ActionCacheOutput ;
1333+
1334+ const replay = await agent . runFromActionCache ( cache , page ) ;
1335+
1336+ expect ( replay . status ) . toBe ( TaskStatus . FAILED ) ;
1337+ const message = replay . steps [ 0 ] ?. message ?? "" ;
1338+ expect ( message ) . toContain ( "Failed to read cached steps" ) ;
1339+ expect ( message ) . toContain ( "[truncated" ) ;
1340+ expect ( message ) . not . toContain ( "\u0000" ) ;
1341+ expect ( message ) . not . toContain ( "\n" ) ;
1342+ } ) ;
1343+
13191344 it ( "fails replay step cleanly when page getter throws" , async ( ) => {
13201345 const agent = new HyperAgent ( {
13211346 llm : createMockLLM ( ) ,
Original file line number Diff line number Diff line change @@ -1949,7 +1949,13 @@ export class HyperAgent<T extends BrowserProviders = "Local"> {
19491949 const shouldWriteReplayDebug = ( ) : boolean =>
19501950 debug && this . isTaskLifecycleGenerationActive ( replayLifecycleGeneration ) ;
19511951 const formatReplayDiagnostic = ( value : unknown ) : string => {
1952- const normalized = formatUnknownError ( value ) . replace ( / \s + / g, " " ) . trim ( ) ;
1952+ const normalized = Array . from ( formatUnknownError ( value ) , ( char ) => {
1953+ const code = char . charCodeAt ( 0 ) ;
1954+ return ( code >= 0 && code < 32 ) || code === 127 ? " " : char ;
1955+ } )
1956+ . join ( "" )
1957+ . replace ( / \s + / g, " " )
1958+ . trim ( ) ;
19531959 const fallback = normalized . length > 0 ? normalized : "unknown error" ;
19541960 if ( fallback . length <= HyperAgent . MAX_REPLAY_DIAGNOSTIC_CHARS ) {
19551961 return fallback ;
You can’t perform that action at this time.
0 commit comments