fix(security): eliminate ReDoS vulnerabilities in compression rules

This commit is contained in:
diegosouzapw
2026-05-04 18:54:06 -03:00
parent 7985f6818e
commit 5ad6df52e0
3 changed files with 9 additions and 12 deletions

View File

@@ -65,9 +65,9 @@ export function compressMcpDescription(description: string): DescriptionCompress
const applied = applyRulesToText(text, rules).text;
const normalized = applied
.replace(/[ \t]{2,}/g, " ")
.replace(/[ \t]+([,.;:!?])/g, "$1")
.replace(/[ \t]([,.;:!?])/g, "$1")
.replace(/\n{3,}/g, "\n\n")
.replace(/(^|[.!?][ \t]+|\n+[ \t]*)([a-z])/g, (_match, prefix: string, char: string) => {
.replace(/(^|[.!?][ \t]|\n[ \t]*)([a-z])/g, (_match, prefix: string, char: string) => {
return `${prefix}${char.toUpperCase()}`;
})
.trim();

View File

@@ -205,7 +205,7 @@ export function applyRulesToText(
function cleanupArtifacts(text: string): string {
let result = text;
if (result.includes(" ")) result = result.replace(/[ \t]{2,}/g, " ");
if (/[\t ]+[,.;:!?]/.test(result)) result = result.replace(/[ \t]+([,.;:!?])/g, "$1");
if (/[\t ]+[,.;:!?]/.test(result)) result = result.replace(/[ \t]([,.;:!?])/g, "$1");
if (/[.!?]{2,}/.test(result)) result = result.replace(/([.!?]){2,}/g, "$1");
if (/[ \t]\n/.test(result)) result = result.replace(/[ \t]+$/gm, "");
if (result.endsWith(" ") || result.endsWith("\t")) result = result.trimEnd();
@@ -216,12 +216,9 @@ function cleanupArtifacts(text: string): string {
}
function recapitalizeSentences(text: string): string {
return text.replace(
/(^|[.!?][ \t]+|\n+[ \t]*)([a-z])/g,
(_match, prefix: string, char: string) => {
return `${prefix}${char.toUpperCase()}`;
}
);
return text.replace(/(^|[.!?][ \t]|\n[ \t]*)([a-z])/g, (_match, prefix: string, char: string) => {
return `${prefix}${char.toUpperCase()}`;
});
}
function createCavemanStats(
@@ -365,7 +362,7 @@ export function cavemanCompress(
const { text: rulesApplied, appliedRules } = applyRulesToText(extractedText, rules);
allAppliedRules.push(...appliedRules);
const normalized = cleanupArtifacts(recapitalizeSentences(rulesApplied));
const normalized = recapitalizeSentences(cleanupArtifacts(rulesApplied));
const cleaned =
blocks.length > 0
? cleanupArtifacts(restorePreservedBlocks(normalized, blocks))

View File

@@ -59,7 +59,7 @@ export function validateCompression(original: string, compressed: string): Valid
);
requireExactPresence(
"markdown link",
collectMatches(original, /\[[^\]\n]{1,1000}\]\([^)[ \t\n]{1,2000}(?:[ \t]+"[^"]{0,1000}")?\)/g),
collectMatches(original, /\[[^\]\n]{1,1000}\]\([^)\n]{1,2000}\)/g),
compressed,
errors
);
@@ -67,7 +67,7 @@ export function validateCompression(original: string, compressed: string): Valid
requireExactPresence("heading", collectMatches(original, /^#{1,6}\s+.+$/gm), compressed, errors);
requireExactPresence(
"table row",
collectMatches(original, /^[ \t]*\|(?:[^|\n]{0,1000}\|){1,100}[ \t]*$/gm),
collectMatches(original, /^[ \t]*\|(?:[^|\n]{0,1000}\|){1,100}/gm),
compressed,
errors
);