fix(mcp): ограничить ELK-лейаут (кап узлов/рёбер + таймаут) — untrusted-граф DoS (ревью #440)
applyElkLayout крутит elkjs СИНХРОННО в процессе на mxGraph-XML от LLM (layout:'elk' в drawio_create/update) без лимита размера и без таймаута — большой граф (тысячи узлов, ~1МБ XML проходит stage-1 cap 16МБ) блокирует event-loop MCP-сервера на секунды-минуты. try/catch ловил только брошенную ошибку, но не зависание. - кап ДО построения графа: >500 узлов или >1000 рёбер → вернуть исходный XML (best-effort, как существующий catch); синхронный elkjs → кап и есть реальная защита; - Promise.race с 5s-таймаутом (defense-in-depth на случай async-elkjs); таймер гасится в finally → нет утечки хендла и unhandled-rejection (проигравший timeout остаётся pending с погашенным таймером); - тест: 600-узловой граф возвращается без изменений и быстро (<2s) — кап-путь. 79/79 drawio-тестов зелёные. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -277,6 +277,14 @@ describe('AiChatToolsService forUser + comment signal (real tracker)', () => {
|
||||
// Wire the REAL factory so the in-app path is exercised end to end.
|
||||
createCommentSignalTracker:
|
||||
createCommentSignalTracker as unknown as loader.CommentSignalTrackerFactory,
|
||||
// Pure no-network draw.io helpers (#424) — required on the loader return;
|
||||
// this comment-signal test doesn't exercise them, so no-op stubs suffice.
|
||||
searchShapes: (() => []) as unknown as loader.SearchShapesFn,
|
||||
getGuideSection: (() => ({
|
||||
section: '',
|
||||
content: '',
|
||||
sections: [],
|
||||
})) as unknown as loader.GetGuideSectionFn,
|
||||
});
|
||||
return new AiChatToolsService(
|
||||
tokenServiceStub as never,
|
||||
|
||||
Reference in New Issue
Block a user