File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -94,4 +94,33 @@ describe("docsSearchCommand", () => {
9494 expect ( runtime . exit ) . not . toHaveBeenCalled ( ) ;
9595 expect ( runtime . log ) . toHaveBeenCalled ( ) ;
9696 } ) ;
97+
98+ it ( "rejects oversized docs search responses" , async ( ) => {
99+ const ONE_MIB = 1024 * 1024 ;
100+ const cancel = vi . fn ( ) ;
101+ const stream = new ReadableStream < Uint8Array > ( {
102+ cancel,
103+ start ( controller ) {
104+ for ( let i = 0 ; i < 10 ; i ++ ) {
105+ controller . enqueue ( new Uint8Array ( ONE_MIB ) ) ;
106+ }
107+ controller . close ( ) ;
108+ } ,
109+ } ) ;
110+ fetchMock . mockResolvedValueOnce (
111+ new Response ( stream , {
112+ status : 200 ,
113+ headers : { "Content-Type" : "application/json" } ,
114+ } ) ,
115+ ) ;
116+ const runtime = makeRuntime ( ) ;
117+
118+ await docsSearchCommand ( [ "oversized" ] , runtime ) ;
119+
120+ expect ( runtime . error ) . toHaveBeenCalledWith (
121+ expect . stringContaining ( "Docs search response exceeds" ) ,
122+ ) ;
123+ expect ( runtime . exit ) . toHaveBeenCalledWith ( 1 ) ;
124+ expect ( cancel ) . toHaveBeenCalledOnce ( ) ;
125+ } ) ;
97126} ) ;
Original file line number Diff line number Diff line change 11// Implements docs link/search output for `openclaw docs`.
2+ import { readResponseWithLimit } from "@openclaw/media-core/read-response-with-limit" ;
23import { formatDocsLink } from "../../packages/terminal-core/src/links.js" ;
34import { isRich , theme } from "../../packages/terminal-core/src/theme.js" ;
45import { formatCliCommand } from "../cli/command-format.js" ;
56import type { RuntimeEnv } from "../runtime.js" ;
67
78const SEARCH_API = "https://docs.openclaw.ai/api/search" ;
89const SEARCH_TIMEOUT_MS = 30_000 ;
10+ const DOCS_SEARCH_RESPONSE_MAX_BYTES = 8 * 1024 * 1024 ;
911
1012type DocResult = {
1113 title : string ;
@@ -75,7 +77,10 @@ async function fetchDocsSearch(query: string): Promise<DocResult[]> {
7577 if ( ! response . ok ) {
7678 throw new Error ( `HTTP ${ response . status } ` ) ;
7779 }
78- const payload = ( await response . json ( ) ) as DocsSearchResponse ;
80+ const bytes = await readResponseWithLimit ( response , DOCS_SEARCH_RESPONSE_MAX_BYTES , {
81+ onOverflow : ( { maxBytes } ) => new Error ( `Docs search response exceeds ${ maxBytes } bytes` ) ,
82+ } ) ;
83+ const payload = JSON . parse ( new TextDecoder ( ) . decode ( bytes ) ) as DocsSearchResponse ;
7984 return parseDocsSearchResults ( payload . results ) ;
8085 } finally {
8186 clearTimeout ( timeout ) ;
You can’t perform that action at this time.
0 commit comments