Skip to content

Integrate Gemini API for AI-Powered Response System in OWASP-BLT #4470

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 1 commit into
base: main
Choose a base branch
from

Conversation

atharva9980
Copy link

@atharva9980 atharva9980 commented Jul 31, 2025

Closes #4378

🔧 Feature: Gemini API Integration

✅ What this PR does

  • Integrates Google Gemini API (gemini-2.5-flash) using secure key from .env.
  • Adds a user-friendly UI at /ask-gemini/ matching the OWASP BLT design.
  • Converts Markdown responses into readable HTML using marked.js.
  • Gemini behaves as a polite security assistant for OWASP-related queries.

📸 Screenshots

Screenshot 2025-07-31 214357

📂 Files Changed

  • website/views/gemini.py
  • website/utils.py
  • website/templates/gemini_input.html
  • website/urls.py
  • Updated .env usage and settings.py

🚀 How to Test

  1. Go to /ask-gemini/
  2. Type a prompt like “How to secure a Django app?”
  3. See the formatted response from Gemini

🔒 Notes

  • Follows project’s styling and UX
  • Gracefully handles errors like missing key or model 404s

further: It will be grateful if you carefully evaluate the work and give me suggestions , I am ready to to further enhance it by modifying its usage to RAG architecture , or agentic AI architecture , generative AI or ML model etc.

Summary by CodeRabbit

  • New Features

    • Introduced a user interface for submitting questions to Gemini, accessible via a new page.
    • Added an API endpoint to process user prompts and return responses from the Gemini language model.
    • Integrated Gemini as a security assistant knowledgeable in cybersecurity and related topics.
  • Configuration

    • Enabled loading of environment variables and added support for a Gemini API key in settings.
    • Updated template and static file configurations for improved template discovery.
  • Improvements

    • Enhanced URL routing to support the new Gemini features and user interface.

… flash model with the context of security tools, and to test the api is ask-gemini
Copy link
Contributor

coderabbitai bot commented Jul 31, 2025

Walkthrough

The changes introduce Gemini AI integration into the Django project. They add environment variable loading for the Gemini API key, new URL routes and view functions for interacting with Gemini, a utility to call the Gemini API, and a user-facing HTML template for submitting prompts. Minor settings and URL configuration adjustments are also included.

Changes

Cohort / File(s) Change Summary
Settings and Environment
blt/settings.py
Added trailing comma and blank line in INSTALLED_APPS, set 'templates' directory in TEMPLATES, loaded environment variables with dotenv, and introduced GEMINI_API_KEY from .env.
Main URL Routing
blt/urls.py
Added imports, included website.urls at root, added admin URL with trailing slash, retained previous admin URL, and appended static file serving for media files.
Website URL Routing
website/urls.py
Created new URL patterns mapping root, Gemini test API, and Gemini UI endpoints to corresponding view functions.
Gemini Integration Utility
website/utils.py
Added call_gemini(prompt) function to send requests to Gemini API and return generated responses.
Gemini Views
website/views/gemini.py
Added gemini_ui view to render the input template and test_gemini view to process user prompts and return Gemini responses as JSON.
Gemini Input Template
website/templates/gemini_input.html
Introduced a new HTML template for user interaction with Gemini, including JavaScript for API communication and markdown rendering.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Browser
    participant DjangoServer
    participant GeminiAPI

    User->>Browser: Open /ask-gemini/
    Browser->>DjangoServer: GET /ask-gemini/
    DjangoServer->>Browser: Render gemini_input.html

    User->>Browser: Enter prompt and submit form
    Browser->>DjangoServer: GET /api/test-gemini/?prompt=...
    DjangoServer->>GeminiAPI: POST prompt to Gemini API
    GeminiAPI-->>DjangoServer: Return generated response
    DjangoServer-->>Browser: JSON response with Gemini output
    Browser->>User: Render response in UI
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~18 minutes

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

response = call_gemini(prompt)
return JsonResponse({"response": response})
except Exception as e:
return JsonResponse({"error": str(e)}, status=500)

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (4)
website/utils.py (1)

27-30: Remove duplicate imports.

The imports for requests and django.conf.settings are already present at the top of the file (lines 15 and 18).

-# website/utils.py
-import requests
-from django.conf import settings
-
website/templates/gemini_input.html (3)

30-46: Add robust fetch error handling

await response.json() will throw on network errors or non-JSON responses, crashing the handler. Guard for !response.ok and wrap the call in try / catch.

-      const response = await fetch('/api/test-gemini/?prompt=' + encodeURIComponent(prompt));
-      const result = await response.json();
+      let result;
+      try {
+        const response = await fetch('/api/test-gemini/?prompt=' + encodeURIComponent(prompt));
+        if (!response.ok) throw new Error(`HTTP ${response.status}`);
+        result = await response.json();
+      } catch (err) {
+        responseContainer.innerHTML = `<p class="text-red-600">Request failed: ${err.message}</p>`;
+        return;
+      }

7-8: Add Sub-Resource Integrity (SRI) & crossorigin for CDN assets

Including external scripts without SRI is a supply-chain risk. Pin exact versions and add integrity hashes. Same applies to Tailwind.


18-19: Disable the submit button while awaiting a response to prevent duplicate requests

UI/UX nit – users can spam the endpoint by repeatedly clicking Submit.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Knowledge Base: Disabled due to Reviews > Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 1d942ad and 027db14.

📒 Files selected for processing (6)
  • blt/settings.py (3 hunks)
  • blt/urls.py (2 hunks)
  • website/templates/gemini_input.html (1 hunks)
  • website/urls.py (1 hunks)
  • website/utils.py (1 hunks)
  • website/views/gemini.py (1 hunks)
🧰 Additional context used
🪛 GitHub Check: CodeQL
website/views/gemini.py

[warning] 16-16: Information exposure through an exception
Stack trace information flows to this location and may be exposed to an external user.

⏰ 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). (5)
  • GitHub Check: auto-assign
  • GitHub Check: Run Tests
  • GitHub Check: docker-test
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
blt/settings.py (1)

169-169: LGTM!

Adding 'templates' to the DIRS list properly enables Django to locate templates in the dedicated templates directory for the new Gemini feature.

website/views/gemini.py (1)

5-6: LGTM!

The UI view correctly renders the Gemini input template.

website/urls.py (1)

1-9: LGTM!

The URL configuration is well-structured with clear routing for the home page, Gemini API endpoint, and UI interface. The import structure and URL patterns follow Django best practices.

Comment on lines +634 to +636
from dotenv import load_dotenv
load_dotenv()
GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consolidate environment variable loading and add API key validation.

There are multiple approaches to loading environment variables in this file. The existing code uses environ.Env.read_env() at lines 14 and 19, and now load_dotenv() is added. This creates redundancy and potential confusion.

Apply this diff to consolidate and add validation:

-from dotenv import load_dotenv
-load_dotenv()
-GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")
+GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")
+if not GEMINI_API_KEY:
+    raise Exception("GEMINI_API_KEY environment variable is required for Gemini integration.")

The existing environ.Env.read_env() calls already handle loading from .env files, making load_dotenv() redundant.

📝 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.

Suggested change
from dotenv import load_dotenv
load_dotenv()
GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")
GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")
if not GEMINI_API_KEY:
raise Exception("GEMINI_API_KEY environment variable is required for Gemini integration.")
🤖 Prompt for AI Agents
In blt/settings.py around lines 634 to 636, remove the redundant load_dotenv()
call and the import from dotenv since environ.Env.read_env() is already used
earlier to load environment variables. Then, add validation to ensure
GEMINI_API_KEY is set by checking if the environment variable is None or empty
and raise an appropriate error if it is missing. This consolidates environment
loading and ensures the API key is validated.

Comment on lines +361 to +368
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
path('', include('website.urls')),
path(settings.ADMIN_URL + "/", admin.site.urls),
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove redundant imports and duplicate admin URL.

The imports at lines 361-364 are redundant as they're already imported at the top of the file. Additionally, there's now a duplicate admin URL pattern.

Apply this diff to clean up the redundancy:

-from django.contrib import admin
-from django.urls import path, include
-from django.conf import settings
-from django.conf.urls.static import static
-
 urlpatterns = [
     path('', include('website.urls')),
-    path(settings.ADMIN_URL + "/", admin.site.urls),

The admin URL is already defined at line 528, making the duplicate at line 368 unnecessary.

📝 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.

Suggested change
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', include('website.urls')),
path(settings.ADMIN_URL + "/", admin.site.urls),
urlpatterns = [
path('', include('website.urls')),
]
🤖 Prompt for AI Agents
In blt/urls.py around lines 361 to 368, remove the redundant imports of admin,
path, include, settings, and static since they are already imported at the top
of the file. Also, delete the duplicate admin URL pattern at line 368 because
the admin URL is already defined at line 528, avoiding duplication in
urlpatterns.


urlpatterns = [
path('', include('website.urls')),
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify URL routing doesn't conflict with existing patterns.

Including website.urls at the root path could potentially conflict with existing URL patterns defined later in the file.


🏁 Script executed:

#!/bin/bash
# Description: Check for potential URL conflicts between website.urls and existing patterns
# Expected: Find any URL patterns that might conflict

# Check what URLs are defined in website.urls
echo "=== URLs in website/urls.py ==="
cat website/urls.py

echo -e "\n=== Checking for potential conflicts ==="
# Look for patterns that might conflict with home, api/test-gemini/, ask-gemini/
rg -A 2 -B 2 "(path\(''\)|path\('api/\)|path\('ask-)" blt/urls.py

Length of output: 605


🏁 Script executed:

#!/bin/bash
set -e

echo "URL prefixes in blt/urls.py:"
# single-quoted
rg -o "path\('[^']*'" blt/urls.py | sed -E "s/path\('([^']*)'/\1/"
# double-quoted
rg -o 'path\("[^"]*"' blt/urls.py | sed -E 's/path\("([^"]*)"/\1/'

echo -e "\nURL prefixes in website/urls.py:"
rg -o "path\('[^']*'" website/urls.py | sed -E "s/path\('([^']*)'/\1/"
rg -o 'path\("[^"]*"' website/urls.py | sed -E 's/path\("([^"]*)"/\1/'

Length of output: 4625


Ensure website.urls doesn’t override all other routes

Including website.urls at the empty prefix as the first entry in blt/urls.py (line 367) will capture every request and, since website/urls.py only defines:

  • '' (home)
  • api/test-gemini/
  • ask-gemini/

any other URL in your project will 404 instead of matching its intended pattern.

Please adjust one of the following:

  • Move
    blt/urls.py:367
  • path('', include('website.urls')),
  • …other patterns here…

  • path('', include('website.urls')), # move below existing routes
  • Or mount under its own prefix, e.g.:
  • path('', include('website.urls')),
  • path('website/', include('website.urls')),

This will ensure your core app and API routes remain reachable.

🤖 Prompt for AI Agents
In blt/urls.py at line 367, including 'website.urls' at the root path causes it
to override all other routes, leading to 404 errors for URLs not defined there.
To fix this, either move this include statement below other route definitions so
those routes take precedence, or mount 'website.urls' under a specific prefix
(e.g., 'website/') to isolate its URL space and prevent it from capturing all
requests.

Comment on lines +37 to +38
const response = await fetch('/api/test-gemini/?prompt=' + encodeURIComponent(prompt));
const result = await response.json();
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use POST (with JSON body & CSRF token) instead of GET to avoid URL length limits and query-string leakage

Long prompts will break on browsers/servers that cap URL size, and sensitive questions end up in logs and browser history. Switch to POST with a JSON payload (and pass Django’s csrftoken).

-      const response = await fetch('/api/test-gemini/?prompt=' + encodeURIComponent(prompt));
-      const result = await response.json();
+      const response = await fetch('/api/test-gemini/', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+          'X-CSRFToken': getCookie('csrftoken')  // helper required
+        },
+        body: JSON.stringify({ prompt })
+      });
+      const result = await response.json();

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In website/templates/gemini_input.html around lines 37 to 38, the code uses a
GET request with query parameters to send the prompt, which risks URL length
limits and leaks sensitive data in logs and history. Change the fetch call to
use POST instead, sending the prompt as a JSON body. Also, include the CSRF
token from Django in the request headers to ensure security. Update the
server-side endpoint to accept POST requests with JSON if needed.

Comment on lines +40 to +43
if (result.response) {
const formatted = marked.parse(result.response);
responseContainer.innerHTML = formatted;
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Sanitize Gemini-generated HTML before injecting it into the DOM

marked.parse() will happily render any HTML the model returns – including <script> tags – leading to a trivial stored/ reflected XSS vector. Never trust LLM output.

-        const formatted = marked.parse(result.response);
-        responseContainer.innerHTML = formatted;
+        // Sanitize to neutralise any hostile markup returned by the model
+        const formatted = DOMPurify.sanitize(marked.parse(result.response));
+        responseContainer.innerHTML = formatted;

Add DOMPurify (or enable marked’s sanitize option, but DOMPurify is battle-tested):

<!-- add right after the marked.js import -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/purify.min.js"
        integrity="sha384-8W+bKHSN50dBprVT2z5jc4azlD2r7rSnPv4XLLF9B8g8nMiZxgJ5Bf5+8b5hvx+H"
        crossorigin="anonymous"></script>
🤖 Prompt for AI Agents
In website/templates/gemini_input.html around lines 40 to 43, the code uses
marked.parse() to convert model output to HTML and injects it directly into the
DOM, which can lead to XSS vulnerabilities if the output contains malicious
scripts. To fix this, include the DOMPurify library by adding its script tag
after the marked.js import, then sanitize the HTML returned by marked.parse()
using DOMPurify.sanitize() before assigning it to responseContainer.innerHTML.

Comment on lines +31 to +56
def call_gemini(prompt: str) -> str:
url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent"
headers = {"Content-Type": "application/json"}

# Add domain-specific context to act like a security assistant
context_prompt = (
"You are Gemini, a helpful, polite assistant integrated into OWASP BLT, a suite of security tools. "
"You help users understand cybersecurity, bug bounty, appsec, secure coding, OWASP Top 10, and other web security concerns. "
"Provide clear, well-formatted answers suitable for developers and researchers. Respond in markdown format."
)

full_prompt = f"{context_prompt}\n\nUser's question: {prompt}"

payload = {
"contents": [{"parts": [{"text": full_prompt}]}]
}

params = {"key": settings.GEMINI_API_KEY}
response = requests.post(url, headers=headers, json=payload, params=params)

data = response.json()
if "candidates" in data:
return data["candidates"][0]["content"]["parts"][0]["text"]
else:
return str(data)

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve security, error handling, and reliability.

Several improvements needed for production readiness:

  1. API key should be in headers, not query parameters
  2. Missing error handling for API response status
  3. No timeout specified for HTTP request
  4. Response parsing could fail if structure is unexpected

Apply this diff to address these issues:

 def call_gemini(prompt: str) -> str:
     url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent"
-    headers = {"Content-Type": "application/json"}
+    headers = {
+        "Content-Type": "application/json",
+        "x-goog-api-key": settings.GEMINI_API_KEY
+    }

     # Add domain-specific context to act like a security assistant
     context_prompt = (
         "You are Gemini, a helpful, polite assistant integrated into OWASP BLT, a suite of security tools. "
         "You help users understand cybersecurity, bug bounty, appsec, secure coding, OWASP Top 10, and other web security concerns. "
         "Provide clear, well-formatted answers suitable for developers and researchers. Respond in markdown format."
     )

     full_prompt = f"{context_prompt}\n\nUser's question: {prompt}"

     payload = {
         "contents": [{"parts": [{"text": full_prompt}]}]
     }

-    params = {"key": settings.GEMINI_API_KEY}
-    response = requests.post(url, headers=headers, json=payload, params=params)
+    response = requests.post(url, headers=headers, json=payload, timeout=30)
+    response.raise_for_status()  # Raise exception for HTTP errors

     data = response.json()
-    if "candidates" in data:
+    if "candidates" in data and len(data["candidates"]) > 0:
+        parts = data["candidates"][0].get("content", {}).get("parts", [])
+        if parts and len(parts) > 0:
+            return parts[0].get("text", "No response generated")
+        else:
+            return "No response content available"
-        return data["candidates"][0]["content"]["parts"][0]["text"]
     else:
-        return str(data)
+        error_msg = data.get("error", {}).get("message", "Unknown API error")
+        raise Exception(f"Gemini API error: {error_msg}")
📝 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.

Suggested change
def call_gemini(prompt: str) -> str:
url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent"
headers = {"Content-Type": "application/json"}
# Add domain-specific context to act like a security assistant
context_prompt = (
"You are Gemini, a helpful, polite assistant integrated into OWASP BLT, a suite of security tools. "
"You help users understand cybersecurity, bug bounty, appsec, secure coding, OWASP Top 10, and other web security concerns. "
"Provide clear, well-formatted answers suitable for developers and researchers. Respond in markdown format."
)
full_prompt = f"{context_prompt}\n\nUser's question: {prompt}"
payload = {
"contents": [{"parts": [{"text": full_prompt}]}]
}
params = {"key": settings.GEMINI_API_KEY}
response = requests.post(url, headers=headers, json=payload, params=params)
data = response.json()
if "candidates" in data:
return data["candidates"][0]["content"]["parts"][0]["text"]
else:
return str(data)
def call_gemini(prompt: str) -> str:
url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent"
headers = {
"Content-Type": "application/json",
"x-goog-api-key": settings.GEMINI_API_KEY
}
# Add domain-specific context to act like a security assistant
context_prompt = (
"You are Gemini, a helpful, polite assistant integrated into OWASP BLT, a suite of security tools. "
"You help users understand cybersecurity, bug bounty, appsec, secure coding, OWASP Top 10, and other web security concerns. "
"Provide clear, well-formatted answers suitable for developers and researchers. Respond in markdown format."
)
full_prompt = f"{context_prompt}\n\nUser's question: {prompt}"
payload = {
"contents": [{"parts": [{"text": full_prompt}]}]
}
response = requests.post(url, headers=headers, json=payload, timeout=30)
response.raise_for_status() # Raise exception for HTTP errors
data = response.json()
if "candidates" in data and len(data["candidates"]) > 0:
parts = data["candidates"][0].get("content", {}).get("parts", [])
if parts and len(parts) > 0:
return parts[0].get("text", "No response generated")
else:
return "No response content available"
else:
error_msg = data.get("error", {}).get("message", "Unknown API error")
raise Exception(f"Gemini API error: {error_msg}")
🤖 Prompt for AI Agents
In website/utils.py lines 31 to 56, the call_gemini function has multiple
issues: the API key should be moved from query parameters to the request headers
for better security; add error handling to check the HTTP response status and
raise or handle errors if the call fails; specify a timeout parameter in the
requests.post call to avoid hanging requests; and add robust parsing of the JSON
response to safely handle unexpected or missing fields, using try-except blocks
or conditional checks to prevent runtime errors.

Comment on lines +8 to +16
def test_gemini(request):
prompt = request.GET.get("prompt")
if not prompt:
return JsonResponse({"error": "No prompt provided"}, status=400)
try:
response = call_gemini(prompt)
return JsonResponse({"response": response})
except Exception as e:
return JsonResponse({"error": str(e)}, status=500)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix information exposure vulnerability.

The exception handling exposes full error details to users, which could leak sensitive information like API keys, internal paths, or system configuration details.

Apply this diff to implement secure error handling:

 def test_gemini(request):
     prompt = request.GET.get("prompt")
     if not prompt:
         return JsonResponse({"error": "No prompt provided"}, status=400)
     try:
         response = call_gemini(prompt)
         return JsonResponse({"response": response})
     except Exception as e:
-        return JsonResponse({"error": str(e)}, status=500)
+        # Log the full error for debugging but return generic message to user
+        import logging
+        logging.error(f"Gemini API error: {str(e)}")
+        return JsonResponse({"error": "An error occurred while processing your request"}, status=500)
📝 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.

Suggested change
def test_gemini(request):
prompt = request.GET.get("prompt")
if not prompt:
return JsonResponse({"error": "No prompt provided"}, status=400)
try:
response = call_gemini(prompt)
return JsonResponse({"response": response})
except Exception as e:
return JsonResponse({"error": str(e)}, status=500)
def test_gemini(request):
prompt = request.GET.get("prompt")
if not prompt:
return JsonResponse({"error": "No prompt provided"}, status=400)
try:
response = call_gemini(prompt)
return JsonResponse({"response": response})
except Exception as e:
# Log the full error for debugging but return a generic message to the user
import logging
logging.error(f"Gemini API error: {e}")
return JsonResponse(
{"error": "An error occurred while processing your request"},
status=500
)
🧰 Tools
🪛 GitHub Check: CodeQL

[warning] 16-16: Information exposure through an exception
Stack trace information flows to this location and may be exposed to an external user.

🤖 Prompt for AI Agents
In website/views/gemini.py around lines 8 to 16, the current exception handling
returns the full error message to the user, risking exposure of sensitive
information. Modify the except block to log the detailed exception internally
for debugging but return a generic error message to the user in the
JsonResponse, such as "An internal error occurred," with a 500 status code to
prevent leaking sensitive details.

@krrish-sehgal
Copy link
Contributor

krrish-sehgal commented Aug 2, 2025

@atharva9980 can you please run

pre-commit run --all-files
before pushing your changes so that the CI passes. Also resolve the conflicts.

Also the issue you have linked is related to one of the GSoC milestones , I suggest you take a look on some other issues , or collaborate with @SahilDhillon21 , if he's fine with it.

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.

Integrate Gemini API in the backend
2 participants