Conversation
- Created a new prompts configuration file (`config/prompts.js`) to centralize AI prompts and schemas. - Updated `manifest.json` to include web accessible resources for inpage scripts. - Refactored `classifyClickbait` method in `ai-manager.js` to utilize the new prompt configuration. - Enhanced `BaitBreakerContentManager` in `content-script.js` to inject prompts into the page context. - Updated `inpage.js` to use injected prompts for classification and summarization. - Adjusted `webpack.config.js` to ensure inpage.js is included in the build process.
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughCentralizes AI prompt schemas, templates, and builders into Changes
Sequence Diagram(s)sequenceDiagram
participant CS as Content Script
participant Page as Web Page
participant Inpage as In-Page Script
participant AI as AI service
CS->>CS: initialize()
CS->>Page: inject <script> setting window.__BB_PROMPTS__
CS->>Page: append inpage.js
Page->>Inpage: inpage.js runs, reads window.__BB_PROMPTS__
Page->>Inpage: classify(title)
Inpage->>Inpage: buildClassificationPrompt(title)
Inpage->>AI: send prompt + CLASSIFICATION_SCHEMA
AI-->>Inpage: classification result
Inpage-->>Page: return classification
Page->>Inpage: summarize(text, context)
Inpage->>Inpage: buildSummarizationContext(context.title)
Inpage->>AI: send summarization request
AI-->>Inpage: summary
Inpage-->>Page: return summary
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull Request Overview
This PR centralizes AI prompt configuration by extracting hardcoded prompts and schemas into a shared configuration file. The prompts are now injected into the in-page script via a global variable, ensuring consistency across different execution contexts (background script, content script, and page context).
- Centralized all AI prompts and schemas in
config/prompts.js - Modified the in-page script to receive prompts via dependency injection through
window.__BB_PROMPTS__ - Updated webpack and manifest configurations to enable proper script injection
Reviewed Changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| config/prompts.js | New file containing centralized prompt templates, schemas, and helper functions |
| src/background/ai-manager.js | Updated to import and use centralized prompts instead of hardcoded values |
| src/content/content-script.js | Added method to inject prompts into page context and load inpage.js |
| src/content/inpage.js | Refactored to accept prompts via window.__BB_PROMPTS__ with fallback defaults |
| manifest.json | Added web_accessible_resources to allow inpage.js to be loaded |
| webpack.config.js | Added copy pattern for inpage.js to dist directory |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| }, | ||
| { from: 'icons', to: 'icons' }, | ||
| { from: 'src/styles', to: 'styles' }, | ||
| { from: 'src/content/inpage.js', to: 'src/content/inpage.js' }, |
There was a problem hiding this comment.
The inpage.js file is being copied directly without transformation, but it contains ES6 module code that won't work in a page context script. Since this file is loaded via a <script> tag in the page context (not as a module), any ES6 imports would fail. Consider either: (1) bundling this file through webpack's entry points like other scripts, or (2) ensuring it doesn't use ES6 module syntax. Currently it uses an IIFE which is correct, but this approach bypasses webpack's bundling and any potential transformations.
| script.textContent = ` | ||
| window.__BB_PROMPTS__ = ${JSON.stringify(prompts)}; |
There was a problem hiding this comment.
The prompts object is serialized using JSON.stringify without sanitization. While the current prompt templates appear safe, if any template values were to contain user input or untrusted data in the future, this could create an XSS vulnerability. Consider adding validation or using a safer serialization approach. Additionally, the template literal creates a script that's directly inserted into the page context, which should be carefully reviewed for any potential injection risks.
| script.textContent = ` | |
| window.__BB_PROMPTS__ = ${JSON.stringify(prompts)}; | |
| // Escape </script> to prevent XSS if any prompt contains it | |
| const safePromptsJSON = JSON.stringify(prompts).replace(/<\/script/gi, '<\\/script'); | |
| script.textContent = ` | |
| window.__BB_PROMPTS__ = ${safePromptsJSON}; |
| CLASSIFICATION_PROMPT_TEMPLATE: 'Analyze if this title is clickbait (uses curiosity gap, emotional triggers, or withholds key information).\nTitle: "{title}"\n\nReturn JSON with fields: isClickbait (boolean), confidence (0-1), reason (short).', | ||
| SUMMARIZATION_CONTEXT_TEMPLATE: 'Answer the clickbait-style question concisely in one short sentence. Title: {title}', |
There was a problem hiding this comment.
The fallback prompt template uses \\n escape sequences which differ from the template literal format used in config/prompts.js (lines 24-27). This inconsistency makes the fallback harder to maintain and could lead to subtle behavioral differences if the fallback is ever used. Consider using a template literal here as well for consistency.
| CLASSIFICATION_PROMPT_TEMPLATE: 'Analyze if this title is clickbait (uses curiosity gap, emotional triggers, or withholds key information).\nTitle: "{title}"\n\nReturn JSON with fields: isClickbait (boolean), confidence (0-1), reason (short).', | |
| SUMMARIZATION_CONTEXT_TEMPLATE: 'Answer the clickbait-style question concisely in one short sentence. Title: {title}', | |
| CLASSIFICATION_PROMPT_TEMPLATE: `Analyze if this title is clickbait (uses curiosity gap, emotional triggers, or withholds key information). |
There was a problem hiding this comment.
This is the final PR Bugbot will review for you during this billing cycle
Your free Bugbot reviews will reset on December 15
Details
You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
| // Check if already injected | ||
| if (window.__BB_INPAGE_INJECTED__) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
src/content/content-script.js (1)
65-78: Escape</script>before inlining promptsEmbedding
JSON.stringify(prompts)directly leaves any</scriptsubstring intact. If a prompt template ever contains it, this inline script terminates early,__BB_PROMPTS__never initializes, and the page-context bridge breaks. Escape the sequence before writing into the DOM.const prompts = { CLASSIFICATION_PROMPT_TEMPLATE, SUMMARIZATION_CONTEXT_TEMPLATE, CLASSIFICATION_SCHEMA }; + const safePromptsJSON = JSON.stringify(prompts).replace(/<\/script/gi, '<\\/script'); // Inject prompts into page context first const script = document.createElement('script'); script.textContent = ` - window.__BB_PROMPTS__ = ${JSON.stringify(prompts)}; + window.__BB_PROMPTS__ = ${safePromptsJSON}; window.__BB_INPAGE_INJECTED__ = true; `;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
config/prompts.js(1 hunks)manifest.json(1 hunks)src/background/ai-manager.js(2 hunks)src/content/content-script.js(3 hunks)src/content/inpage.js(2 hunks)webpack.config.js(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
config/prompts.js (1)
src/content/inpage.js (1)
PROMPTS(5-17)
src/content/inpage.js (1)
config/prompts.js (4)
PROMPTS(56-62)PROMPTS(56-62)buildClassificationPrompt(34-36)buildSummarizationContext(49-51)
src/background/ai-manager.js (1)
config/prompts.js (3)
buildClassificationPrompt(34-36)CLASSIFICATION_SCHEMA(10-18)CLASSIFICATION_SCHEMA(10-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Cursor Bugbot
🔇 Additional comments (4)
config/prompts.js (4)
10-18: LGTM! Well-structured schema definition.The JSON Schema is properly defined with appropriate type constraints and required fields.
24-27: LGTM! Clear and well-structured prompt template.The template provides clear instructions for clickbait classification.
42-42: LGTM! Concise summarization template.The template is clear and appropriate for its use case.
56-62: LGTM! Clean aggregated export.The PROMPTS object provides a convenient single export for all prompt-related functionality.
| export function buildClassificationPrompt(title) { | ||
| return CLASSIFICATION_PROMPT_TEMPLATE.replace('{title}', title.replace(/"/g, '\\"')); | ||
| } |
There was a problem hiding this comment.
Add input validation and comprehensive escaping.
This function has multiple issues:
- Runtime error risk: If
titleisnullorundefined, calling.replace()will throw a TypeError. - Incomplete escaping: Only escaping double quotes is insufficient. Consider:
- Backslashes before quotes (e.g.,
title = 'test\\"') could break the escaping - Newlines, tabs, and other control characters could disrupt the prompt structure
- Potential prompt injection attacks via unescaped special characters
- Backslashes before quotes (e.g.,
Apply this diff to add validation and more robust escaping:
export function buildClassificationPrompt(title) {
+ if (typeof title !== 'string') {
+ throw new TypeError('Title must be a string');
+ }
+ // Escape backslashes first, then quotes, then newlines
+ const escaped = title
+ .replace(/\\/g, '\\\\')
+ .replace(/"/g, '\\"')
+ .replace(/\n/g, '\\n')
+ .replace(/\r/g, '\\r')
+ .replace(/\t/g, '\\t');
- return CLASSIFICATION_PROMPT_TEMPLATE.replace('{title}', title.replace(/"/g, '\\"'));
+ return CLASSIFICATION_PROMPT_TEMPLATE.replace('{title}', escaped);
}🤖 Prompt for AI Agents
In config/prompts.js around lines 34–36, the buildClassificationPrompt function
currently assumes title is a string and only escapes double quotes; update it to
validate and robustly escape input: first check title is non-null/undefined
(throw an Error or return a safe default if invalid), coerce to String, then
perform escaping in the correct order (escape backslashes first, then double
quotes), replace control characters (newline, carriage return, tab and other
non-printables) with safe escape sequences (e.g. \n, \r, \t or remove), and
optionally enforce a maximum length; finally use the escaped string in
CLASSIFICATION_PROMPT_TEMPLATE.replace('{title}', escapedTitle).
| export function buildSummarizationContext(title = '') { | ||
| return SUMMARIZATION_CONTEXT_TEMPLATE.replace('{title}', title); | ||
| } |
There was a problem hiding this comment.
Critical: Missing input escaping creates prompt injection vulnerability.
Unlike buildClassificationPrompt, this function does not escape the title parameter before inserting it into the prompt. This creates a security vulnerability where malicious or unexpected input could:
- Inject arbitrary instructions into the AI prompt
- Manipulate the AI's behavior
- Produce unexpected or harmful outputs
Additionally, the inconsistency between the two builder functions creates confusion and maintenance issues.
Apply this diff to add proper validation and escaping:
export function buildSummarizationContext(title = '') {
+ if (typeof title !== 'string') {
+ title = String(title);
+ }
+ // Escape special characters to prevent prompt injection
+ const escaped = title
+ .replace(/\\/g, '\\\\')
+ .replace(/\n/g, '\\n')
+ .replace(/\r/g, '\\r')
+ .replace(/\t/g, '\\t');
- return SUMMARIZATION_CONTEXT_TEMPLATE.replace('{title}', title);
+ return SUMMARIZATION_CONTEXT_TEMPLATE.replace('{title}', escaped);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function buildSummarizationContext(title = '') { | |
| return SUMMARIZATION_CONTEXT_TEMPLATE.replace('{title}', title); | |
| } | |
| export function buildSummarizationContext(title = '') { | |
| if (typeof title !== 'string') { | |
| title = String(title); | |
| } | |
| // Escape special characters to prevent prompt injection | |
| const escaped = title | |
| .replace(/\\/g, '\\\\') | |
| .replace(/\n/g, '\\n') | |
| .replace(/\r/g, '\\r') | |
| .replace(/\t/g, '\\t'); | |
| return SUMMARIZATION_CONTEXT_TEMPLATE.replace('{title}', escaped); | |
| } |
🤖 Prompt for AI Agents
In config/prompts.js around lines 49-51, the buildSummarizationContext function
inserts the raw title into the prompt template which creates a prompt-injection
vulnerability; update the function to mirror buildClassificationPrompt by
validating and escaping the title before replacing it into
SUMMARIZATION_CONTEXT_TEMPLATE (e.g., trim, enforce a sensible max length,
sanitize/escape characters that could alter prompt structure, and reuse the
existing escape helper used by buildClassificationPrompt), then replace the
template placeholder with the escaped value and add a small unit test to cover
malicious/edge-case titles.
Move prompts to config folder
Add AI prompts configuration and integrate into content scripts
config/prompts.js) to centralize AI prompts and schemas.manifest.jsonto include web accessible resources for inpage scripts.classifyClickbaitmethod inai-manager.jsto utilize the new prompt configuration.BaitBreakerContentManagerincontent-script.jsto inject prompts into the page context.inpage.jsto use injected prompts for classification and summarization.webpack.config.jsto ensure inpage.js is included in the build process.Summary by CodeRabbit
Refactor
New Features
Chores
Note
Centralizes AI prompts/schema and updates background, content, and inpage scripts to use injected prompts, exposing/copying inpage.js via manifest and build config.
config/prompts.jswithCLASSIFICATION_SCHEMA, prompt templates, and builders (buildClassificationPrompt,buildSummarizationContext).src/background/ai-manager.jsto usebuildClassificationPromptandCLASSIFICATION_SCHEMAforclassifyClickbait.src/content/content-script.jsto inject prompts into page context (window.__BB_PROMPTS__) and loadsrc/content/inpage.js.src/content/inpage.jsto consume injected prompts, build prompts/context helpers, and applyresponseConstraintfromCLASSIFICATION_SCHEMA.web_accessible_resourcesforsrc/content/inpage.js.webpack.config.jsto copysrc/content/inpage.jsinto the build.Written by Cursor Bugbot for commit 5052014. This will update automatically on new commits. Configure here.