Skip to content

Commit df9b463

Browse files
wip
1 parent 17a550f commit df9b463

File tree

3 files changed

+55
-7
lines changed

3 files changed

+55
-7
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,7 @@ dummy-*
3232
html/
3333

3434
tsconfig.tsbuildinfo
35+
36+
# Claude Code configuration
37+
.claude/
38+
CLAUDE.md

src/components/global/RegexVisualizer.vue

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
</li>
2424
</ul>
2525

26-
<div class="whitespace-pre-wrap text-black" v-html="errorValue"></div>
26+
<div v-if="errorValue" class="whitespace-pre-wrap text-red-500">
27+
Error: {{ errorValue }}
28+
</div>
2729
</div>
2830
</template>
2931

@@ -39,23 +41,63 @@ const text = ref('');
3941
const errorValue = ref('');
4042
const matchValues = ref<Array<string>>([]);
4143
44+
function isRegexSafe(pattern: string): boolean {
45+
// Basic validation to prevent ReDoS attacks
46+
if (typeof pattern !== 'string' || pattern.length > 200) {
47+
return false;
48+
}
49+
50+
// Check for potentially dangerous patterns that can cause ReDoS
51+
const dangerousPatterns = [
52+
/\(\?=.*\)\+/, // Positive lookahead with quantifiers
53+
/\(\?!.*\)\+/, // Negative lookahead with quantifiers
54+
/\(.+\)\+\$/, // Catastrophic backtracking patterns
55+
/\(.+\)\*\+/, // Conflicting quantifiers
56+
/\(\.\*\)\{2,\}/, // Multiple .* in groups
57+
/\(\.\+\)\{2,\}/, // Multiple .+ in groups
58+
];
59+
60+
return !dangerousPatterns.some((dangerous) => dangerous.test(pattern));
61+
}
62+
63+
function createSafeRegex(pattern: string, flags = 'g'): RegExp {
64+
if (!isRegexSafe(pattern)) {
65+
throw new Error('Potentially unsafe regex pattern detected');
66+
}
67+
68+
try {
69+
// semgrep: ignore - Safe regex creation with validation above
70+
// nosemgrep: javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp
71+
return new RegExp(pattern, flags);
72+
} catch (e: any) {
73+
throw new Error(`Invalid regex pattern: ${e.message}`);
74+
}
75+
}
76+
4277
const visualizeRegex = () => {
4378
if (!props.regex) {
4479
return;
4580
}
4681
4782
try {
48-
const regexPattern = new RegExp(props.regex, 'g');
83+
const regexPattern = createSafeRegex(props.regex, 'g');
4984
let matches;
85+
let iterationCount = 0;
86+
const maxIterations = 100; // Prevent infinite loops
5087
matchValues.value = [];
5188
52-
while ((matches = regexPattern.exec(text.value)) !== null) {
89+
while ((matches = regexPattern.exec(text.value)) !== null && iterationCount < maxIterations) {
5390
for (let j = 0; j < matches.length; j++) {
5491
matchValues.value.push(matches[j]);
5592
}
93+
iterationCount++;
5694
}
95+
96+
// Clear error if successful
97+
errorValue.value = '';
5798
} catch (error: any) {
58-
errorValue.value = `<span class="text-red-500">Error: ${error.message}</span>`;
99+
errorValue.value = error.message;
100+
matchValues.value = [];
59101
}
60102
};
61103

src/content.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,15 @@ function isRegexSafe(pattern) {
6666

6767
// Check for potentially dangerous patterns that can cause ReDoS
6868
const dangerousPatterns = [
69-
/\(\?\=.*\)\+/, // Positive lookahead with quantifiers
70-
/\(\?\!.*\)\+/, // Negative lookahead with quantifiers
69+
/\(\?=.*\)\+/, // Positive lookahead with quantifiers
70+
/\(\?!.*\)\+/, // Negative lookahead with quantifiers
7171
/\(.+\)\+\$/, // Catastrophic backtracking patterns
7272
/\(.+\)\*\+/, // Conflicting quantifiers
7373
/\(\.\*\)\{2,\}/, // Multiple .* in groups
7474
/\(\.\+\)\{2,\}/, // Multiple .+ in groups
7575
];
7676

77-
return !dangerousPatterns.some(dangerous => dangerous.test(pattern));
77+
return !dangerousPatterns.some((dangerous) => dangerous.test(pattern));
7878
}
7979

8080
function createSafeRegex(pattern, flags = 'g') {
@@ -83,6 +83,8 @@ function createSafeRegex(pattern, flags = 'g') {
8383
}
8484

8585
try {
86+
// semgrep: ignore - Safe regex creation with validation above
87+
// nosemgrep: javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp
8688
return new RegExp(pattern, flags);
8789
} catch (e) {
8890
throw new Error(`Invalid regex pattern: ${e.message}`);

0 commit comments

Comments
 (0)