-
Notifications
You must be signed in to change notification settings - Fork 2
chore: sync core lib and CLAUDE.md from agent-core #42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -114,8 +114,11 @@ const CRITICAL_PATTERNS = [ | |||||||||||||||
| const SUBAGENT_PATTERN = /subagent_type\s*[=:]\s*["']([^"']+)["']/g; | ||||||||||||||||
|
|
||||||||||||||||
| /** Pre-compiled patterns for cleaning content */ | ||||||||||||||||
| const BAD_EXAMPLE_TAG_PATTERN = /<bad[_\- ]?example>[\s\S]*?<\/bad[_\- ]?example>/gi; | ||||||||||||||||
| const BAD_EXAMPLE_CODE_PATTERN = /```[^\n]*bad[^\n]*\n[\s\S]*?```/gi; | ||||||||||||||||
| // ReDoS fix: bound the lazy [\s\S]*? bodies so an unterminated <bad-example> or | ||||||||||||||||
| // ``` fence cannot drive polynomial backtracking; 50k chars covers any realistic | ||||||||||||||||
| // example block, so the stripped regions are unchanged for real content. | ||||||||||||||||
| const BAD_EXAMPLE_TAG_PATTERN = /<bad[_\- ]?example>[\s\S]{0,50000}?<\/bad[_\- ]?example>/gi; | ||||||||||||||||
| const BAD_EXAMPLE_CODE_PATTERN = /```[^\n]{0,500}bad[^\n]{0,500}\n[\s\S]{0,50000}?```/gi; | ||||||||||||||||
|
Comment on lines
+117
to
+121
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The original regular expressions for stripping bad examples do not possess ReDoS vulnerabilities. Lazy matching over all characters (
Suggested change
|
||||||||||||||||
|
|
||||||||||||||||
| // ============================================ | ||||||||||||||||
| // TOOL PATTERN CACHE | ||||||||||||||||
|
|
@@ -649,10 +652,14 @@ function analyzePromptConsistency(agents) { | |||||||||||||||
|
|
||||||||||||||||
| // Extract action keywords | ||||||||||||||||
| let action; | ||||||||||||||||
| // ReDoS fix: bound the greedy prefix to non-newline chars. `line` is a single | ||||||||||||||||
| // trimmed line (no newlines), so [^\n]{0,N} is equivalent to the prior `.*`: | ||||||||||||||||
| // greedy match strips everything up to and including the LAST keyword plus its | ||||||||||||||||
| // trailing whitespace, preserving the word-boundary semantics exactly. | ||||||||||||||||
| if (isAlways) { | ||||||||||||||||
| action = line.replace(/.*\bALWAYS\b\s*/i, '').substring(0, ACTION_COMPARISON_LENGTH); | ||||||||||||||||
| action = line.replace(/[^\n]{0,2000}\bALWAYS\b\s{0,200}/i, '').substring(0, ACTION_COMPARISON_LENGTH); | ||||||||||||||||
| } else { | ||||||||||||||||
| action = line.replace(/.*\b(?:NEVER|DO NOT)\b\s*/i, '').substring(0, ACTION_COMPARISON_LENGTH); | ||||||||||||||||
| action = line.replace(/[^\n]{0,2000}\b(?:NEVER|DO NOT)\b\s{0,200}/i, '').substring(0, ACTION_COMPARISON_LENGTH); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| // Extract significant keywords from action | ||||||||||||||||
|
|
||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -24,7 +24,9 @@ const docsPatterns = { | |||||||||
| if (!content || typeof content !== 'string') return null; | ||||||||||
|
|
||||||||||
| // Find markdown links | ||||||||||
| const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g; | ||||||||||
| // ReDoS fix: bound the negated-class captures so the matcher is linear; | ||||||||||
| // bounds far exceed any realistic markdown link, so matches are unchanged. | ||||||||||
| const linkRegex = /\[([^\]]{1,2000})\]\(([^)]{1,4000})\)/g; | ||||||||||
|
Comment on lines
+27
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The original regular expression
Suggested change
|
||||||||||
| const brokenLinks = []; | ||||||||||
| let match; | ||||||||||
|
|
||||||||||
|
|
@@ -40,7 +42,9 @@ const docsPatterns = { | |||||||||
| if (linkTarget.startsWith('#')) { | ||||||||||
| const anchorId = linkTarget.slice(1).toLowerCase(); | ||||||||||
| // Generate expected heading anchors from content | ||||||||||
| const headings = content.match(/^#{1,6}\s+(.+)$/gm) || []; | ||||||||||
| // ReDoS fix: bound the \s+ run; line-anchored (.+) cannot cross newlines | ||||||||||
| // so the same headings match as before. | ||||||||||
| const headings = content.match(/^#{1,6}\s{1,1000}(.+)$/gm) || []; | ||||||||||
| const anchors = headings.map(h => { | ||||||||||
| return h.replace(/^#{1,6}\s+/, '') | ||||||||||
| .toLowerCase() | ||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original regular expression
/module\\.exports\\s*=\\s*\\{([^}]+)\\}/is completely safe from ReDoS. The negated character class[^}]+is terminated by the literal\\}, meaning there is no ambiguity or overlapping paths for the regex engine to backtrack exponentially.\n\nLimiting the capture to 100,000 characters ({1,100000}) will cause the parser to fail on large, valid JavaScript files (such as large configuration files, localized translation dictionaries, or auto-generated asset maps) where the exported object exceeds 100KB.\n\nWe should revert this to the original safe pattern.