Skip to content

[DX-1958] Add "Ask AI" to docs website #6317

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

Merged
merged 61 commits into from
May 13, 2025
Merged

[DX-1958] Add "Ask AI" to docs website #6317

merged 61 commits into from
May 13, 2025

Conversation

sharadregoti
Copy link
Contributor

@sharadregoti sharadregoti commented Apr 17, 2025

User description

Preview Link

Checklist

  • Added a preview link
  • Reviewed AI PR Agent suggestions
  • For Tyk Members - Added Jira DX PR ticket to the subject
  • For Tyk Members - Added the appropriate release labels (for fixes add the latest release)

New Contributors


PR Type

Enhancement, Documentation


Description

  • Introduces an interactive AI chat widget to the docs site.

  • Adds frontend logic for streaming AI responses with markdown support.

  • Implements custom styles for chat UI and markdown rendering.

  • Integrates widget into site layout via a new partial template.


Changes walkthrough 📝

Relevant files
Enhancement
ai-chat-widget.html
Introduce AI chat widget partial with UI and dependencies

tyk-docs/themes/tykio/layouts/partials/ai-chat-widget.html

  • Adds a new partial for the AI chat widget UI.
  • Includes chat bubble, popup, input, and message display.
  • Loads required CSS/JS for Tailwind, Highlight.js, and Marked.js.
  • References custom chat styles and logic scripts.
  • +36/-0   
    chat.js
    Add frontend logic for AI chat widget with streaming         

    tyk-docs/static/js/chat.js

  • Implements chat widget logic for user input and message streaming.
  • Handles SSE streaming from backend and dynamic markdown rendering.
  • Manages UI state, typing indicator, and error handling.
  • Integrates syntax highlighting for code blocks in responses.
  • +264/-0 
    chat.css
    Add custom CSS for chat widget and markdown rendering       

    tyk-docs/static/css/chat.css

  • Adds custom styles for chat widget layout and responsiveness.
  • Styles markdown content, typing indicator, and chat popup.
  • Ensures mobile responsiveness for the chat popup.
  • +217/-0 
    baseof.html
    Integrate AI chat widget partial into base layout               

    tyk-docs/themes/tykio/layouts/_default/baseof.html

  • Integrates the AI chat widget partial into the site base template.
  • Ensures widget loads on all pages by including the partial.
  • +3/-1     

    Need help?
  • Type /help how to ... in the comments thread for any questions about PR-Agent usage.
  • Check out the documentation for more information.
  • Copy link
    Contributor

    github-actions bot commented Apr 17, 2025

    PR Reviewer Guide 🔍

    (Review updated until commit d2091f5)

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
    🧪 No relevant tests
    🔒 Security concerns

    XSS vulnerability:
    The chat widget renders markdown using the marked library with sanitize: false, which can allow malicious HTML/JS injection if the AI or user input is not properly sanitized. This is a significant security concern and should be addressed before deploying to production.

    ⚡ Recommended focus areas for review

    XSS Risk in Markdown Rendering

    The use of marked.parse(accumulatedText) with sanitize: false can allow untrusted markdown content to inject HTML/JS, leading to XSS vulnerabilities. This should be reviewed and sanitized before rendering user or AI-generated content.

    marked.setOptions({
      renderer: new marked.Renderer(),
      highlight: function (code, language) {
        const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
        return hljs.highlight(code, { language: validLanguage }).value;
      },
      pedantic: false,
      gfm: true,
      breaks: true,
      sanitize: false,
      smartypants: false,
      xhtml: false
    });
    Hardcoded API Endpoint

    The API endpoint for streaming responses is hardcoded to a specific URL. This may cause issues in different environments (development, staging, production) and should be configurable.

    fetch('https://tyk-docs-ask-ai.dokku.tyk.technology/api/stream', {
      method: 'POST',
      headers: headers,
      body: JSON.stringify({ prompt: message }),
      signal: signal
    }).then(response => {
    External Script and Style Dependencies

    The widget loads external scripts and styles from CDNs (Tailwind, Highlight.js, Marked.js). This can introduce reliability and security risks if the CDN is compromised or unavailable. Consider local hosting or integrity checks.

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.16/tailwind.min.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/styles/github.min.css">
    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/highlight.min.js"></script>
    <link rel="stylesheet" href="css/chat.css">
    <script defer src="js/chat.js"></script>

    Copy link
    Contributor

    PR Code Suggestions ✨

    No code suggestions found for the PR.

    Copy link

    netlify bot commented Apr 17, 2025

    PS. Pls add /docs/nightly to the end of url

    Name Link
    🔨 Latest commit cf20324
    🔍 Latest deploy log https://app.netlify.com/sites/tyk-docs/deploys/6822f1ae2f7f210008df63f3
    😎 Deploy Preview https://deploy-preview-6317--tyk-docs.netlify.app
    📱 Preview on mobile
    Toggle QR Code...

    QR Code

    Use your smartphone camera to open QR code link.

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

    @sharadregoti sharadregoti marked this pull request as draft April 17, 2025 07:01
    @sharadregoti sharadregoti marked this pull request as ready for review April 24, 2025 15:17
    @sharadregoti
    Copy link
    Contributor Author

    /help "can you review the PR again"

    @sharadregoti
    Copy link
    Contributor Author

    /probe "Can you review the PR?"

    Copy link
    Contributor

    github-actions bot commented May 9, 2025

    Code Review: Add "Ask AI" to docs website (Updated)

    Overview

    This PR adds an AI chat widget to the Tyk documentation website, allowing users to ask questions about Tyk products and receive AI-generated responses. The implementation has been significantly improved from the initial version.

    Positive Changes

    1. Security Improvements

    The critical XSS vulnerability has been addressed by enabling sanitization in marked.js:

    marked.setOptions({
      // ...
      sanitize: true, // Enable sanitization to prevent XSS
      // ...
    });

    2. Enhanced UI/UX

    • Added an overlay for the chat popup for better visual hierarchy
    • Improved mobile responsiveness with proper media queries
    • Added a stop button to cancel ongoing requests
    • Better typing indicators and message styling

    3. Improved Error Handling

    The code now handles different error scenarios more gracefully:

    if (error.name === 'AbortError') {
      rawContentContainer.textContent = 'Request was cancelled.';
    } else {
      rawContentContainer.textContent = 'Sorry, something went wrong with the streaming connection.';
    }

    4. Better Code Organization

    • Structured message history with proper role-based format
    • Separated markdown rendering into its own function
    • Improved stream processing with better buffer management

    Remaining Issues

    1. Hardcoded API Endpoint

    The API endpoint is still hardcoded:

    fetch('https://tyk-docs-ask-ai.dokku.tyk.technology/api/stream', {
      method: 'POST',
      headers: headers,
      body: JSON.stringify({ messages: messages }),
      signal: signal
    })

    Recommendation: Make the endpoint configurable via environment variables or a config object:

    const apiEndpoint = window.TYK_CONFIG?.aiChatEndpoint || '/api/ai/stream';
    fetch(apiEndpoint, {
      // ...
    })

    2. External Dependencies Without SRI

    The widget still loads external scripts without Subresource Integrity (SRI) checks:

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/styles/github.min.css">
    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/highlight.min.js"></script>

    Recommendation: Add SRI hashes to ensure the integrity of external resources:

    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js" 
      integrity="sha384-[hash]" crossorigin="anonymous"></script>

    3. Accessibility Improvements

    While the UI has improved, there are still some accessibility enhancements that could be made:

    Recommendation: Add ARIA attributes to improve screen reader support:

    <div id="chat-bubble" aria-label="Open chat assistant" role="button" tabindex="0" class="...">

    Summary

    This PR has significantly improved from its initial implementation, particularly in addressing the critical XSS vulnerability. The UI/UX enhancements and better error handling make for a more robust user experience.

    The remaining issues are relatively minor and could be addressed in follow-up PRs. The hardcoded API endpoint is the most important remaining issue as it could cause deployment problems across different environments.

    Overall, with the security improvements in place, this PR is in good shape for merging, though addressing the hardcoded endpoint would be strongly recommended before deployment to production.


    Tip: Mention me again using /probe <request>.
    Powered by Probe AI

    @letzya letzya requested a review from yurisasuke May 9, 2025 13:03
    buger and others added 2 commits May 13, 2025 09:04
    @sharadregoti
    Copy link
    Contributor Author

    /probe "We are using marked.js v15.0.11, but from the review and from marked.js it is found that the sanitize field has been removed since v8. The docs say it was removed in v8.0.0 and recommends using a sanitize library, like DOMPurify (recommended), sanitize-html, or insane on the output HTML! Can you review the PR and suggest fixes?"

    Copy link
    Contributor

    Security Issue: XSS Vulnerability in AI Chat Widget

    Problem Identified

    The AI chat widget is using marked.js version 15.0.11 with the sanitize: true option, but this option was deprecated and removed in marked.js version 8.0.0. This creates a potential XSS vulnerability because:

    1. The sanitize option is being silently ignored in the current version
    2. The HTML generated from markdown is not being sanitized before insertion into the DOM
    3. This could allow malicious code injection if the AI returns unsafe content

    Solution: Implement DOMPurify for HTML Sanitization

    Since marked.js no longer handles sanitization internally, we need to add a dedicated HTML sanitization library. The marked.js documentation recommends DOMPurify as the preferred solution.

    Step 1: Add DOMPurify to the HTML file

    <!-- In ai-chat-widget.html, add this before the chat.js script -->
    <script src="https://cdn.jsdelivr.net/npm/dompurify@3.0.6/dist/purify.min.js"></script>

    Step 2: Remove the deprecated sanitize option

    // In chat.js - Update the marked.js configuration
    marked.setOptions({
      renderer: new marked.Renderer(),
      highlight: function (code, language) {
        const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
        return hljs.highlight(code, { language: validLanguage }).value;
      },
      pedantic: false,
      gfm: true,
      breaks: true,
      // Remove this line as it's no longer supported:
      // sanitize: true, 
      smartypants: false,
      xhtml: false
    });

    Step 3: Update the renderMarkdown function to use DOMPurify

    // In chat.js - Update the renderMarkdown function
    function renderMarkdown(accumulatedText, container) {
      // Reset UI
      chatStop.classList.add('hidden');
      chatSubmit.classList.remove('hidden');
      activeController = null;
      try {
        const markdownContainer = document.createElement('div');
        markdownContainer.className = 'markdown-content';
        
        // Convert markdown to HTML
        const rawHtml = marked.parse(accumulatedText);
        
        // Sanitize the HTML with DOMPurify before inserting into DOM
        const sanitizedHtml = DOMPurify.sanitize(rawHtml);
        markdownContainer.innerHTML = sanitizedHtml;
        
        container.replaceWith(markdownContainer);
    
        // Add assistant response to history
        if (accumulatedText) {
          messagesHistory.push({
            role: "assistant",
            content: accumulatedText
          });
        }
    
        document.querySelectorAll('pre code').forEach((block) => {
          hljs.highlightElement(block);
        });
      } catch (error) {
        console.error('Error rendering final markdown:', error);
      }
    }

    Step 4: Also sanitize user input in onUserRequest function

    Since user input is also directly inserted into the DOM, it should be sanitized as well:

    function onUserRequest(message) {
      // Display user message
      const messageElement = document.createElement('div');
      messageElement.className = 'user-message';
      
      // Sanitize user input before inserting into DOM
      const sanitizedMessage = DOMPurify.sanitize(message);
      messageElement.innerHTML = `
          <div class="message-bubble user-bubble">
            ${sanitizedMessage}
          </div>
        `;
      chatMessages.appendChild(messageElement);
      chatMessages.scrollTop = chatMessages.scrollHeight;
    
      // Rest of the function remains the same...
    }

    Additional Recommendations

    1. Consider using SRI (Subresource Integrity) for the external scripts to prevent supply chain attacks:
    <script src="https://cdn.jsdelivr.net/npm/dompurify@3.0.6/dist/purify.min.js" 
            integrity="sha384-..." 
            crossorigin="anonymous"></script>
    1. Make the API endpoint configurable rather than hardcoded:
    // At the top of the file, define a configurable endpoint
    const API_ENDPOINT = window.TYK_DOCS_AI_ENDPOINT || 'https://tyk-docs-ask-ai.dokku.tyk.technology/api/stream';
    
    // Then use it in the fetch call
    fetch(API_ENDPOINT, {
      // ...
    })
    1. Remove console.log statements before deploying to production for better performance and security.

    By implementing these changes, you'll properly secure the AI chat widget against XSS vulnerabilities while maintaining all the functionality.


    Tip: Mention me again using /probe <request>.
    Powered by Probe AI

    @sharadregoti sharadregoti changed the title Add "Ask AI" to docs website [DX-1958] Add "Ask AI" to docs website May 13, 2025
    @sharadregoti sharadregoti merged commit 6c160f5 into master May 13, 2025
    13 checks passed
    @sharadregoti sharadregoti deleted the add-ask-ai branch May 13, 2025 07:23
    @sharadregoti
    Copy link
    Contributor Author

    /release to release-5.8

    Copy link

    tykbot bot commented May 13, 2025

    Working on it! Note that it can take a few minutes.

    tykbot bot pushed a commit that referenced this pull request May 13, 2025
    (cherry picked from commit 6c160f5)
    Copy link

    tykbot bot commented May 13, 2025

    @sharadregoti Created merge PRs

    buger added a commit that referenced this pull request May 13, 2025
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    4 participants