8000 Enhance multi svm search updated by 0xrinegade · Pull Request #43 · aldrin-labs/opensvm · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Enhance multi svm search updated #43

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

Open
wants to merge 29 commits into
base: main
Choose a base branch
from

Conversation

0xrinegade
Copy link
Member
@0xrinegade 0xrinegade commented May 22, 2025

This pull request introduces significant enhancements to the multi-SVM search user experience, including AI-powered features, improved blockchain data integration, and a more interactive and visually appealing interface. Key updates include the integration of the OpenRouter API for AI-driven blockchain analysis, enhanced Moralis API support, new data visualization components, and performance optimizations. Additionally, the search interface has been upgraded with smooth animations and unified multi-platform search capabilities.

AI Enhancements and Blockchain Data Integration:

  • Integrated OpenRouter API for intelligent blockchain data analysis, including context-aware model selection and streaming responses. [1] [2] [3]
  • Enhanced Moralis API integration to utilize all endpoints, added caching, and implemented error handling with rate-limiting protection.

Search Interface Improvements:

  • Replaced the existing search bar with the new EnhancedSearchBar component across multiple files (HomeSearch.tsx, search/page.tsx). [1] [2]
  • Added AI-enhanced results panel with streaming responses, source citations, and a toggleable UI.
  • Introduced multi-platform search tabs for Solana VM, Telegram, DuckDuckGo, and X.com.

Data Visualizations and User Experience:

  • Created interactive components for visualizing token data, NFT metadata, account portfolios, and transaction details.
  • Added smooth animations using Framer Motion across the search interface, including hover effects and transitions. [1] [2]

Performance Optimizations:

  • Implemented caching, batch processing, and relevance scoring for search results to improve performance and response times.
  • Enhanced UI responsiveness with transition effects and deduplication of search results. [1] [2]

Documentation and Testing:

  • Added comprehensive documentation in docs/enhanced-search.md covering features, components, and API integration.
  • Verified AI responses, search functionality, animations, and visualizations with various datasets during testing.

Summary by Sourcery

Provide an AI-powered, multi-platform search experience with enriched blockchain data visualizations, smooth animated UI components and performance optimizations.

New Features:

  • Introduce AI-enhanced search panel with streaming responses, context-aware model selection and source citations
  • Support unified search across Solana VM, Telegram, DuckDuckGo, and X.com
  • Add interactive data visualizations for tokens, NFTs, accounts, and transactions
  • Replace search bar with enhanced animated component including suggestions, keyboard shortcuts, and search settings

Enhancements:

  • Integrate Moralis API for comprehensive blockchain data retrieval with caching, rate-limit protection and error handling
  • Implement performance optimizations including caching, batch processing, deduplication and relevance scoring
  • Apply smooth animations and transitions via Framer Motion throughout the search interface
  • Refine unified search module to aggregate and optimize results from multiple sources

Documentation:

  • Add detailed documentation covering enhanced search features, API integration and visualization components

Tests:

  • Add end-to-end search testing script covering unified, source-specific, filtered and performance scenarios

agentfarmx bot and others added 14 commits March 25, 2025 17:22
The commit implements a feature-rich search experience by replacing the basic
HomeSearch component with a new EnhancedSearchBar. This adds advanced filtering
capabilities with network selection, data type filtering, sorting options, and
date/amount range filters.
Ensure at least one network and data type remain selected, add helpful
messages, and set defaults when no data types are selected.
refactor: modularize search bar component into smaller components
```
feat: implement search bar theme integration and command+k shortcut
fix: update Select component to use theme variables instead of hardco…
Copy link
sourcery-ai bot commented May 22, 2025

Reviewer's Guide

This PR refactors the search feature by integrating AI-powered analysis via OpenRouter, enhancing blockchain data retrieval with a comprehensive Moralis API client, overhauling the UI with a consolidated EnhancedSearchBar and multi-source tabs, and introducing interactive data visualization components—all while adding caching, batch processing, and relevance scoring for performance and augmenting documentation and tests.

Sequence Diagram for AI-Powered Search

sequenceDiagram
    actor User
    participant ESP as EnhancedSearchBar
    participant ARP as AIResponsePanel
    participant OR_API as OpenRouter API
    participant M_API as Moralis API

    User->>ESP: Enters search query
    ESP->>ARP: Displays and passes query
    ARP->>M_API: Request comprehensive blockchain data (query)
    M_API-->>ARP: Return blockchain data
    ARP->>OR_API: Request AI analysis (query, blockchain data)
    activate OR_API
    OR_API-->>ARP: Stream AI response
    deactivate OR_API
    ARP->>User: Display AI-enhanced results and sources
Loading

Sequence Diagram for Multi-Platform Search

sequenceDiagram
    actor User
    participant ESP as EnhancedSearchBar
    participant USL as UnifiedSearchLib
    participant SVM_API as SVM API
    participant TG_API as Telegram API
    participant DDG_API as DuckDuckGo API
    participant X_API as X.com API

    User->>ESP: Enters search query
    User->>ESP: Selects search sources (e.g., SVM, Telegram)
    ESP->>USL: unifiedSearch(query, options)
    activate USL
    USL->>SVM_API: Search SVM (query)
    SVM_API-->>USL: SVM results
    USL->>TG_API: Search Telegram (query)
    TG_API-->>USL: Telegram results
    USL->>DDG_API: Search DuckDuckGo (query)
    DDG_API-->>USL: DuckDuckGo results
    USL->>X_API: Search X.com (query)
    X_API-->>USL: X.com results
    USL-->>ESP: Combined and formatted results
    deactivate USL
    ESP->>User: Display multi-platform search results
Loading

File-Level Changes

Change Details Files
Integrate AI-driven blockchain analysis
  • Add AI state hooks and streaming logic in SearchResults
  • Introduce AIResponsePanel component with tabbed AI/data views
  • Implement openrouter-api module for model selection, prompt building, streaming
app/search/page.tsx
components/search/AIResponsePanel.tsx
lib/openrouter-api.ts
Enhance Moralis blockchain data integration
  • Develop moralis-api client with caching, rate-limit handling, multiple endpoints
  • Expose getComprehensiveBlockchainData to aggregate token, NFT, account, transaction data
lib/moralis-api.ts
Revamp search interface and input components
  • Replace legacy search bars with EnhancedSearchBar across pages
  • Add multi-platform search tabs (SVM, Telegram, DuckDuckGo, X.com)
  • Inject SearchPopup in providers for global /, Ctrl+K activation
app/search/page.tsx
components/HomeSearch.tsx
components/NavbarInteractive.tsx
app/providers.tsx
components/search/*
components/EnhancedSearchBar.tsx
components/SearchPopup.tsx
Introduce interactive data visualization components
  • Create TransactionVisualization, AccountVisualization, NFTVisualization, TokenVisualization
  • Use Recharts and Framer Motion for charts and animations
components/blockchain-visualizations/TransactionVisualization.tsx
components/blockchain-visualizations/AccountVisualization.tsx
components/blockchain-visualizations/NFTVisualization.tsx
components/blockchain-visualizations/TokenVisualization.tsx
Implement performance optimizations for search results
  • Add unified-search module combining multiple sources with caching
  • Develop search-optimization with batch processing, deduplication, relevance scoring
lib/unified-search.ts
lib/search-optimization.ts
Update documentation and add test scripts
  • Add enhanced-search.md with feature and usage guides
  • Introduce test-search.ts to validate unified search and sources
docs/enhanced-search.md
scripts/test-search.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
netlify bot commented May 22, 2025

Deploy Preview for opensvm ready!

Name Link
🔨 Latest commit 43bdd3c
🔍 Latest deploy log https://app.netlify.com/projects/opensvm/deploys/68305ec4f6826d0008f902b0
😎 Deploy Preview https://deploy-preview-43--opensvm.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 61 (🔴 down 4 from production)
Accessibility: 97 (no change from production)
Best Practices: 75 (🔴 down 17 from production)
SEO: 100 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
@devloai devloai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Summary:

This PR enhances the multi-SVM search experience with AI-powered features, integration of OpenRouter API for blockchain analysis, improved Moralis API support, and a more interactive interface. Key additions include the EnhancedSearchBar component, AI-enhanced results panel with streaming responses, multi-platform search capabilities across Solana VM/Telegram/DuckDuckGo/X.com, and interactive data visualizations for blockchain data.

Review Summary:

My review identified several critical security issues related to hardcoded API keys and potential XSS vulnerabilities that should be addressed before merging. I also found a few bugs including race conditions in error handling and improper routing patterns. The code demonstrates a sophisticated approach to unified search and AI integration, but needs security improvements to meet production standards. Please provide feedback on this review which I'll consider for future reviews.

Follow-up suggestions:

@devloai implement proper API key security using environment variables only
@devloai add proper error handling for missing API keys

import axios from 'axios';

// OpenRouter API configuration
const OPENROUTER_API_KEY = process.env.OPENROUTER_API_KEY || 'sk-or-v1-free-tier-demo-key';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OpenRouter API key is exposed with a default fallback value. Even if it's a free tier key, API keys should never be included in the source code. Instead, handle missing API keys with a proper error and implement a better fallback mechanism.

import axios from 'axios';

// Moralis API configuration
const MORALIS_API_KEY = process.env.MORALIS_API_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJub25jZSI6IjRjOTdiNjY5LWU0NTAtNDc0ZC04NDk5LWM3MzQ3MTY2MzZjZSIsIm9yZ0lkIjoiNDM3NTQzIiwidXNlcklkIjoiNDUwMTMwIiwidHlwZUlkIjoiZjY3MzczODctNjQ1MC00YzIyLTg1YjAtOWI1ZjE3NWE3ZWQ3IiwidHlwZSI6IlBST0pFQ1QiLCJpYXQiOjE3NDI2MzYxMDcsImV4cCI6NDg5ODM5NjEwN30.bLDNejPrPEg9tFbmUITy9cpuMBuvU5pzbloq0b-7r4A';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A hardcoded Moralis API key is included in the source code. This is a serious security risk as API keys should never be committed to repositories. Instead, rely solely on environment variables and implement proper error handling when keys are missing.

// Create prompt with blockchain data
const prompt = openrouter.createBlockchainSearchPrompt(searchQuery, data);

// Switch to streaming mode
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential race condition in error handling. If the blockchainDataPromise fails, you're still trying to use data in the streaming response which could be undefined. Restructure this to ensure the AI response generation only proceeds if blockchain data is successfully retrieved, or implement proper null checking when passing data to openrouter.createBlockchainSearchPrompt.

${date ? `<span class="text-xs text-muted-foreground">${formattedDate}</span>` : ''}
</div>
<p class="mt-1 text-sm">${result.content}</p>
${result.url ? `
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The renderUnifiedSearchResult function outputs raw HTML without proper sanitization. This could lead to XSS vulnerabilities if result content contains malicious scripts. Implement proper HTML sanitization for user-generated or API-provided content before rendering.

window.location.href = `/token/${trimmedQuery}`;
break;
case 'program':
window.location.href = `/program/${trimmedQuery}`;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Direct window location manipulation in the search handling logic can cause issues with Next.js routing and history management. Replace window.location.href with the Next.js router for client-side navigation:

Suggested change
window.location.href = `/program/${trimmedQuery}`;
router.push(`/program/${trimmedQuery}`);

// Handle rate limiting
if (error.response && error.response.status === 429) {
console.error('Rate limit exceeded for Moralis API. Retrying after delay...');
await new Promise(resolve => setTimeout(resolve, 2000));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rate limiting retry mechanism uses a fixed 2 second delay. Consider implementing an exponential backoff strategy for retries to better handle extended rate limiting periods and reduce unnecessary API calls during high traffic.

)}

<button
>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For better accessibility, the close button should include an aria-label attribute to help screen reader users identify its purpose.

Copy link
@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @0xrinegade - I've reviewed your changes and found some issues that need to be addressed.

Blocking issues:

  • Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data. (link)
  • Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data. (link)
  • JWT token detected (link)
  • Returning raw HTML string risks XSS (link)

General comments:

  • This PR touches many areas (AI integration, API enhancements, UI/UX, visualizations); consider breaking it up into smaller, focused PRs so each feature can be reviewed and tested independently.
  • There’s a lot of repeated logic (AI streaming, prompt generation, chart setup) scattered inline in components—extracting these into reusable hooks or utility modules will reduce duplication and improve maintainability.
  • Most visualization components share similar setup (ResponsiveContainer wrappers, Card headers, skeletons); consider abstracting common chart boilerplate into a shared component or HOC to keep your code DRY.
Here's what I looked at during the review
  • 🟡 General issues: 17 issues found
  • 🔴 Security: 3 blocking issues
  • 🟡 Testing: 1 issue found
  • 🟡 Complexity: 4 issues found
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

setIsAiThinking(true);

// Simulate API call delay
const thinkingTimer = setTimeout(() => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Timers not fully cleaned up on unmount

Capture both thinkingTimer and streamInterval in the outer scope and clear them in the useEffect cleanup to prevent memory leaks.

}
}, 15); // Stream characters at a natural typing speed

return () => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Misplaced cleanup return

The return should be directly inside the useEffect to ensure React calls the cleanup function. Move the cleanup logic out of the setTimeout callback.

)}
</div>
)}
<button
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): AI panel close has no reopen control

After closing the AI panel, users cannot reopen it without refreshing the page. Please add a way to toggle the panel back on.

Suggested implementation:

              <button 
                onClick={() => setShowAiPanel(false)}
                className="text-muted-foreground hover:text-foreground transition-colors duration-200"
              >
                <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
                  <path fillRule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clipRule="evenodd" />
                </svg>
              </button>
            </div>
          </CardHeader>
          <CardContent className="p-4">
            {isAiThinking ? (
              <div className="h-24 flex items-center justify-center">
=======
{/* Add this toggle button outside the AI panel, e.g. at the top of the page/component */}
{!showAiPanel && (
  <button
    onClick={() => setShowAiPanel(true)}
    className="fixed bottom-4 right-4 z-50 bg-background border border-border rounded-full shadow-lg px-4 py-2 text-sm text-muted-foreground hover:text-foreground transition-colors duration-200"
    aria-label="Open AI Panel"
  >
    <svg xmlns="http://www.w3.org/2000/svg" className="inline h-5 w-5 mr-1" viewBox="0 0 20 20" fill="currentColor">
      <path d="M10 2a8 8 0 100 16 8 8 0 000-16zm1 11H9v-1h2v1zm0-3H9V7h2v3z" />
    </svg>
    Open AI Panel
  </button>
)}
  • Make sure that showAiPanel and setShowAiPanel are defined in the parent component's state (likely via useState). If not, add:
    const [showAiPanel, setShowAiPanel] = useState(true);
    at the top of your component.
  • Place the new toggle button outside the conditional rendering of the AI panel, so it is always available when the panel is closed.
  • Adjust the button's position and style as needed to fit your UI/UX.

return response.data;
} catch (error: any) {
// Handle rate limiting
if (error.response && error.response.status === 429) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Infinite retry loop on rate limit

Currently, repeated 429 responses will cause endless retries. Please implement a maximum retry limit or exponential backoff to prevent this.

* @param result - Search result to render
* @returns HTML string for the result card
*/
export function renderUnifiedSearchResult(result: UnifiedSearchResult): string {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 issue (security): Returning raw HTML string risks XSS

Consider returning React elements or sanitized content to prevent XSS vulnerabilities.

import axios from 'axios';

// Moralis API configuration
const MORALIS_API_KEY = process.env.MORALIS_API_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJub25jZSI6IjRjOTdiNjY5LWU0NTAtNDc0ZC04NDk5LWM3MzQ3MTY2MzZjZSIsIm9yZ0lkIjoiNDM3NTQzIiwidXNlcklkIjoiNDUwMTMwIiwidHlwZUlkIjoiZjY3MzczODctNjQ1MC00YzIyLTg1YjAtOWI1ZjE3NWE3ZWQ3IiwidHlwZSI6IlBST0pFQ1QiLCJpYXQiOjE3NDI2MzYxMDcsImV4cCI6NDg5ODM5NjEwN30.bLDNejPrPEg9tFbmUITy9cpuMBuvU5pzbloq0b-7r4A';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (detected-jwt-token): JWT token detected

Source: opengrep


// AI Response Generation
useEffect(() => {
if (!query) return;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
if (!query) return;
if (!query) {


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).

Comment on lines +88 to +92
if (rarity < 50) rarityDistribution[0].value++;
else if (rarity < 70) rarityDistribution[1].value++;
else if (rarity < 85) rarityDistribution[2].value++;
else if (rarity < 95) rarityDistribution[3].value++;
else rarityDistribution[4].value++;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
if (rarity < 50) rarityDistribution[0].value++;
else if (rarity < 70) rarityDistribution[1].value++;
else if (rarity < 85) rarityDistribution[2].value++;
else if (rarity < 95) rarityDistribution[3].value++;
else rarityDistribution[4].value++;
if (rarity < 50) {
rarityDistribution[0].value++;
} else if (rarity < 70) rarityDistribution[1].value++;
else if (rarity < 85) rarityDistribution[2].value++;
else if (rarity < 95) rarityDistribution[3].value++;
else rarityDistribution[4].value++;


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).

Comment on lines +89 to +92
else if (rarity < 70) rarityDistribution[1].value++;
else if (rarity < 85) rarityDistribution[2].value++;
else if (rarity < 95) rarityDistribution[3].value++;
else rarityDistribution[4].value++;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
else if (rarity < 70) rarityDistribution[1].value++;
else if (rarity < 85) rarityDistribution[2].value++;
else if (rarity < 95) rarityDistribution[3].value++;
else rarityDistribution[4].value++;
else if (rarity < 70) {
rarityDistribution[1].value++;
} else if (rarity < 85) rarityDistribution[2].value++;
else if (rarity < 95) rarityDistribution[3].value++;
else rarityDistribution[4].value++;


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).

Comment on lines +90 to +92
else if (rarity < 85) rarityDistribution[2].value++;
else if (rarity < 95) rarityDistribution[3].value++;
else rarityDistribution[4].value++;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
else if (rarity < 85) rarityDistribution[2].value++;
else if (rarity < 95) rarityDistribution[3].value++;
else rarityDistribution[4].value++;
else if (rarity < 85) {
rarityDistribution[2].value++;
} else if (rarity < 95) rarityDistribution[3].value++;
else rarityDistribution[4].value++;


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).

url: `https://t.me/${channel.id}`
},
sender: {
username: `user_${Math.random().toString(36).substring(2, 10)}`,

Check failure

Code scanning / CodeQL

Insecure randomness High

This uses a cryptographically insecure random number generated at
Math.random()
in a security context.

Copilot Autofix

AI 17 days ago

To fix the issue, replace the use of Math.random() with a cryptographically secure random number generator. In Node.js, the crypto module provides a secure method for generating random values. Specifically, crypto.randomBytes can be used to generate random bytes, which can then be converted to a string for use in the username.

The fix involves:

  1. Importing the crypto module.
  2. Replacing the Math.random() call with a secure random string generated using crypto.randomBytes.
  3. Ensuring the generated string is of the same format and length as the original.

Suggested changeset 1
7438
lib/telegram-search.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/lib/telegram-search.ts b/lib/telegram-search.ts
--- a/lib/telegram-search.ts
+++ b/lib/telegram-search.ts
@@ -1 +1,2 @@
+import * as crypto from 'crypto';
 /**
@@ -80,3 +81,3 @@
       sender: {
-        username: `user_${Math.random().toString(36).substring(2, 10)}`,
+        username: `user_${crypto.randomBytes(6).toString('base64url').substring(0, 8)}`,
         displayName: generateRandomName()
EOF
@@ -1 +1,2 @@
import * as crypto from 'crypto';
/**
@@ -80,3 +81,3 @@
sender: {
username: `user_${Math.random().toString(36).substring(2, 10)}`,
username: `user_${crypto.randomBytes(6).toString('base64url').substring(0, 8)}`,
displayName: generateRandomName()
Copilot is powered by AI and may make mistakes. Always verify output.
const results = [];

for (let i = 0; i < Math.min(limit, 20); i++) {
const account = accounts[Math.floor(Math.random() * accounts.length)];

Check failure

Code scanning / CodeQL

Insecure randomness High

This uses a cryptographically insecure random number generated at
Math.random()
in a security context.

Copilot Autofix

AI 16 days ago

To fix the issue, we will replace all instances of Math.random() with a cryptographically secure random number generator. In Node.js, the crypto module provides a secure method for generating random values. Specifically, we will use crypto.randomInt() to generate random integers securely. This ensures that the randomness is not predictable and meets cryptographic standards.

The changes will involve:

  1. Importing the crypto module at the top of the file.
  2. Replacing Math.random() with crypto.randomInt() in all relevant locations, ensuring the functionality remains the same.

Suggested changeset 1
lib/xcom-search.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/lib/xcom-search.ts b/lib/xcom-search.ts
--- a/lib/xcom-search.ts
+++ b/lib/xcom-search.ts
@@ -1 +1,2 @@
+import * as crypto from 'crypto';
 /**
@@ -66,4 +67,4 @@
   for (let i = 0; i < Math.min(limit, 20); i++) {
-    const account = accounts[Math.floor(Math.random() * accounts.length)];
-    const tweetTemplate = tweetTemplates[Math.floor(Math.random() * tweetTemplates.length)];
+    const account = accounts[crypto.randomInt(0, accounts.length)];
+    const tweetTemplate = tweetTemplates[crypto.randomInt(0, tweetTemplates.length)];
     const tweet = tweetTemplate.replace('{query}', query);
@@ -71,6 +72,6 @@
     // Random date within last 7 days
-    const timestamp = new Date(Date.now() - Math.floor(Math.random() * 7 * 24 * 60 * 60 * 1000));
+    const timestamp = new Date(Date.now() - crypto.randomInt(0, 7 * 24 * 60 * 60 * 1000));
     
     results.push({
-      id: `tweet_${Math.random().toString(36).substring(2, 15)}`,
+      id: `tweet_${crypto.randomBytes(8).toString('hex')}`,
       type: 'x_com',
@@ -88,3 +89,3 @@
       replies: Math.floor(Math.random() * 200),
-      url: `https://x.com/${account.handle}/status/${Math.random().toString(36).substring(2, 15)}`
+      url: `https://x.com/${account.handle}/status/${crypto.randomBytes(8).toString('hex')}`
     });
EOF
@@ -1 +1,2 @@
import * as crypto from 'crypto';
/**
@@ -66,4 +67,4 @@
for (let i = 0; i < Math.min(limit, 20); i++) {
const account = accounts[Math.floor(Math.random() * accounts.length)];
const tweetTemplate = tweetTemplates[Math.floor(Math.random() * tweetTemplates.length)];
const account = accounts[crypto.randomInt(0, accounts.length)];
const tweetTemplate = tweetTemplates[crypto.randomInt(0, tweetTemplates.length)];
const tweet = tweetTemplate.replace('{query}', query);
@@ -71,6 +72,6 @@
// Random date within last 7 days
const timestamp = new Date(Date.now() - Math.floor(Math.random() * 7 * 24 * 60 * 60 * 1000));
const timestamp = new Date(Date.now() - crypto.randomInt(0, 7 * 24 * 60 * 60 * 1000));

results.push({
id: `tweet_${Math.random().toString(36).substring(2, 15)}`,
id: `tweet_${crypto.randomBytes(8).toString('hex')}`,
type: 'x_com',
@@ -88,3 +89,3 @@
replies: Math.floor(Math.random() * 200),
url: `https://x.com/${account.handle}/status/${Math.random().toString(36).substring(2, 15)}`
url: `https://x.com/${account.handle}/status/${crypto.randomBytes(8).toString('hex')}`
});
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +46 to +48
const sanitized = text
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, '')

Check failure

Code scanning / CodeQL

Incomplete multi-character sanitization High

This string may still contain
<iframe
, which may cause an HTML element injection vulnerability.

Copilot Autofix

AI 16 days ago

To fix the issue, we will modify the sanitizeAiResponseText function to repeatedly apply the regular expression replacements until no further matches are found. This ensures that all instances of the targeted patterns are removed, even if they are nested or malformed. This approach is a straightforward way to address the incomplete sanitization issue without introducing significant complexity.


Suggested changeset 1
lib/ai-utils.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/lib/ai-utils.ts b/lib/ai-utils.ts
--- a/lib/ai-utils.ts
+++ b/lib/ai-utils.ts
@@ -45,6 +45,11 @@
   // Remove any potentially harmful HTML
-  const sanitized = text
-    .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
-    .replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, '')
-    .replace(/<img[^>]*>/gi, '[IMAGE]');
+  let sanitized = text;
+  let previous;
+  do {
+    previous = sanitized;
+    sanitized = sanitized
+      .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
+      .replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, '')
+      .replace(/<img[^>]*>/gi, '[IMAGE]');
+  } while (sanitized !== previous);
   
EOF
@@ -45,6 +45,11 @@
// Remove any potentially harmful HTML
const sanitized = text
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, '')
.replace(/<img[^>]*>/gi, '[IMAGE]');
let sanitized = text;
let previous;
do {
previous = sanitized;
sanitized = sanitized
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, '')
.replace(/<img[^>]*>/gi, '[IMAGE]');
} while (sanitized !== previous);

Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +46 to +47
const sanitized = text
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')

Check failure

Code scanning / CodeQL

Incomplete multi-character sanitization High

This string may still contain
<script
, which may cause an HTML element injection vulnerability.

Copilot Autofix

AI 16 days ago

To fix the issue, we will modify the sanitizeAiResponseText function to repeatedly apply the regular expression replacements until no more matches are found. This ensures that all instances of the targeted patterns are removed, even if they are nested or malformed. Additionally, we will recommend using a well-tested sanitization library like sanitize-html for more robust and comprehensive sanitization.

Suggested changeset 1
lib/ai-utils.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/lib/ai-utils.ts b/lib/ai-utils.ts
--- a/lib/ai-utils.ts
+++ b/lib/ai-utils.ts
@@ -45,6 +45,11 @@
   // Remove any potentially harmful HTML
-  const sanitized = text
-    .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
-    .replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, '')
-    .replace(/<img[^>]*>/gi, '[IMAGE]');
+  let sanitized = text;
+  let previous;
+  do {
+    previous = sanitized;
+    sanitized = sanitized
+      .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
+      .replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, '')
+      .replace(/<img[^>]*>/gi, '[IMAGE]');
+  } while (sanitized !== previous);
   
EOF
@@ -45,6 +45,11 @@
// Remove any potentially harmful HTML
const sanitized = text
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, '')
.replace(/<img[^>]*>/gi, '[IMAGE]');
let sanitized = text;
let previous;
do {
previous = sanitized;
sanitized = sanitized
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, '')
.replace(/<img[^>]*>/gi, '[IMAGE]');
} while (sanitized !== previous);

Copilot is powered by AI and may make mistakes. Always verify output.
export function sanitizeAiResponseText(text: string): string {
// Remove any potentially harmful HTML
const sanitized = text
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')

Check failure

Code scanning / CodeQL

Bad HTML filtering regexp High

This regular expression does not match script end tags like </script >.

Copilot Autofix

AI 16 days ago

The best way to fix this issue is to replace the custom regular expression-based sanitization with a well-tested HTML sanitization library, such as DOMPurify. These libraries are specifically designed to handle edge cases and ensure that potentially harmful HTML is removed safely. This approach is more robust and secure than attempting to fix the regex manually.

To implement the fix:

  1. Install the dompurify library.
  2. Replace the custom regex-based sanitization logic in the sanitizeAiResponseText function with a call to DOMPurify.sanitize.
  3. Ensure that the library is imported and properly configured.

Suggested changeset 2
lib/ai-utils.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/lib/ai-utils.ts b/lib/ai-utils.ts
--- a/lib/ai-utils.ts
+++ b/lib/ai-utils.ts
@@ -43,9 +43,7 @@
 // Utility function to sanitize AI response text
+import DOMPurify from 'dompurify';
+
 export function sanitizeAiResponseText(text: string): string {
-  // Remove any potentially harmful HTML
-  const sanitized = text
-    .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
-    .replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, '')
-    .replace(/<img[^>]*>/gi, '[IMAGE]');
-  
+  // Use DOMPurify to sanitize the input text
+  const sanitized = DOMPurify.sanitize(text, { ALLOWED_TAGS: [], ALLOWED_ATTR: [] });
   return sanitized;
EOF
@@ -43,9 +43,7 @@
// Utility function to sanitize AI response text
import DOMPurify from 'dompurify';

export function sanitizeAiResponseText(text: string): string {
// Remove any potentially harmful HTML
const sanitized = text
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, '')
.replace(/<img[^>]*>/gi, '[IMAGE]');

// Use DOMPurify to sanitize the input text
const sanitized = DOMPurify.sanitize(text, { ALLOWED_TAGS: [], ALLOWED_ATTR: [] });
return sanitized;
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -85,3 +85,4 @@
     "zod": "^3.24.1",
-    "zod-to-json-schema": "^3.23.0"
+    "zod-to-json-schema": "^3.23.0",
+    "dompurify": "^3.2.6"
   },
EOF
@@ -85,3 +85,4 @@
"zod": "^3.24.1",
"zod-to-json-schema": "^3.23.0"
"zod-to-json-schema": "^3.23.0",
"dompurify": "^3.2.6"
},
This fix introduces these dependencies
Package Version Security advisories
dompurify (npm) 3.2.6 None
Copilot is powered by AI and may make mistakes. Always verify output.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant
0