Просмотр исходного кода

fix(suggest-path): replace generic HTML stripping with ES highlight tag removal

Strip only known Elasticsearch highlight tags (<em class='highlighted-keyword'>
and </em>) instead of iteratively removing all HTML tags. This eliminates
the CodeQL incomplete sanitization warning and improves performance by
removing the convergence loop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
VANELLOPE\tomoyuki-t 1 месяц назад
Родитель
Сommit
51bea6b041

+ 2 - 4
apps/app/src/features/ai-tools/suggest-path/server/services/retrieve-search-candidates.spec.ts

@@ -272,15 +272,13 @@ describe('retrieveSearchCandidates', () => {
       expect(result[0].snippet).toBe('React hooks ... custom hooks pattern');
     });
 
-    it('should strip all HTML tags from snippets', async () => {
+    it('should strip ES highlight tags from snippets', async () => {
       const searchResult = createSearchResult([
         {
           path: '/tech/React/hooks',
           score: 15,
           highlight: {
-            body: [
-              "<em class='highlighted-keyword'>React</em> <strong>hooks</strong>",
-            ],
+            body: ["<em class='highlighted-keyword'>React</em> hooks"],
           },
         },
       ]);

+ 6 - 9
apps/app/src/features/ai-tools/suggest-path/server/services/retrieve-search-candidates.ts

@@ -14,14 +14,11 @@ export type RetrieveSearchCandidatesOptions = {
   scoreThreshold?: number;
 };
 
-function stripHtmlTags(html: string): string {
-  let previous: string;
-  let result = html;
-  do {
-    previous = result;
-    result = result.replace(/<[^>]*>/g, '');
-  } while (result !== previous);
-  return result;
+// Elasticsearch highlights use <em class='highlighted-keyword'> and </em>
+const ES_HIGHLIGHT_TAG_REGEX = /<\/?em[^>]*>/g;
+
+function stripHighlightTags(text: string): string {
+  return text.replace(ES_HIGHLIGHT_TAG_REGEX, '');
 }
 
 function extractSnippet(item: SearchResultItem): string {
@@ -36,7 +33,7 @@ function extractSnippet(item: SearchResultItem): string {
     return '';
   }
 
-  return stripHtmlTags(fragments.join(' ... '));
+  return stripHighlightTags(fragments.join(' ... '));
 }
 
 export const retrieveSearchCandidates = async (