-
Notifications
You must be signed in to change notification settings - Fork 5
Initial AI Assistant implementation (fixes #8) #13
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements an AI Assistant feature for the InsecureWebApp application, fixing issue #8. The AI Assistant uses OpenAI's API to provide a chat interface where users can ask health-related questions and receive responses from an AI assistant.
- Adds a complete AI Assistant blueprint with chat functionality
- Integrates OpenAI API for conversational AI responses
- Updates navigation to include AI Assistant link
- Updates documentation for static analysis and Debricked scanning
Reviewed Changes
Copilot reviewed 9 out of 11 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| iwa/templates/base.html | Adds styles block and AI Assistant navigation link |
| iwa/blueprints/assistant/templates/assistant/index.html | Complete chat interface template with message display and input form |
| iwa/blueprints/assistant/static/css/assistant.css | Comprehensive styling for the chat interface components |
| iwa/blueprints/assistant/assistant_routes.py | Backend logic for OpenAI integration and chat endpoints |
| iwa/blueprints/assistant/init.py | Blueprint initialization and registration |
| iwa/init.py | Registers the assistant blueprint with the application |
| etc/InsecureWebApp-Prod-Login.webmacro | Updates encrypted configuration file |
| README.md | Adds documentation for static analysis scanning commands |
| .github/workflows/debricked.yml | Simplifies Debricked scanning workflow to use GitHub Actions |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| # Initialize the OpenAI client | ||
| api_key = os.getenv("OPENAI_API_KEY") | ||
| if api_key: | ||
| logger.debug("OPENAI_API_KEY: %s", api_key) |
Copilot
AI
Sep 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logging the full API key in debug mode exposes sensitive credentials in log files. Consider logging only a masked version (e.g., first/last 4 characters) or removing this debug statement entirely.
| logger.debug("OPENAI_API_KEY: %s", api_key) | |
| masked_key = api_key[:4] + "*" * (len(api_key) - 8) + api_key[-4:] if len(api_key) > 8 else "*" * len(api_key) | |
| logger.debug("OPENAI_API_KEY: %s", masked_key) |
| # Initialize the assistant and thread globally | ||
| assistant_id = "" | ||
| thread_id = "" |
Copilot
AI
Sep 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using global variables for assistant_id and thread_id creates potential race conditions in multi-threaded environments. These should be stored per-session or user to avoid conflicts between concurrent users.
| # Define a global chat history | ||
| chat_history = [ | ||
| {"role": "system", "content": "You are a helpful assistant."}, | ||
| ] |
Copilot
AI
Sep 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Global chat_history will be shared across all users and sessions, causing privacy issues and data corruption. Chat history should be stored per-session using Flask's session object or a database.
| # Define a global chat history | |
| chat_history = [ | |
| {"role": "system", "content": "You are a helpful assistant."}, | |
| ] | |
| # Chat history will be stored per-session using Flask's session object. | |
| # To initialize chat history for a session, use: | |
| # if 'chat_history' not in session: | |
| # session['chat_history'] = [{"role": "system", "content": "You are a helpful assistant."}] |
|
|
||
| @assistant_bp.route('/chat', methods=['POST']) | ||
| def chat(): | ||
| content = request.json["message"] |
Copilot
AI
Sep 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing input validation allows potential crashes if request.json is None or doesn't contain 'message' key. Add proper validation and error handling to prevent server errors from malformed requests.
| content = request.json["message"] | |
| if not request.is_json: | |
| return jsonify(success=False, message="Request must be JSON"), 400 | |
| data = request.get_json() | |
| if not data or "message" not in data: | |
| return jsonify(success=False, message="Missing 'message' in request"), 400 | |
| content = data["message"] |
| while run.status != "completed": | ||
| time.sleep(0.5) | ||
| run = client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run.id) | ||
|
|
Copilot
AI
Sep 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This infinite loop with polling could hang indefinitely if the OpenAI API fails or returns an unexpected status. Add a timeout mechanism and maximum retry count to prevent blocking the application.
| while run.status != "completed": | |
| time.sleep(0.5) | |
| run = client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run.id) | |
| max_retries = 40 # 0.5s * 40 = 20 seconds max wait | |
| retries = 0 | |
| while run.status != "completed" and retries < max_retries: | |
| time.sleep(0.5) | |
| run = client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run.id) | |
| retries += 1 | |
| if run.status != "completed": | |
| logger.error("OpenAI API run did not complete after %d retries.", max_retries) | |
| return jsonify(success=False, message="The AI Assistant did not respond in time. Please try again later.") |
|
|
||
| // Load IDs | ||
| $.getJSON("/assistant/get_ids", function (data) { | ||
| console.log("Data: ", data, "Assistant ID: ", data.assistant_id, "Thread ID: ", data.thread_id); |
Copilot
AI
Sep 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logging sensitive data like assistant and thread IDs to the browser console exposes internal system information. Remove or replace with non-sensitive debug information.
| console.log("Data: ", data, "Assistant ID: ", data.assistant_id, "Thread ID: ", data.thread_id); | |
| // Successfully fetched assistant and thread IDs. |
|
|
||
| var messageDiv = $("<div>").addClass(msg.role === "user" ? "user-message" : "assistant-message"); | ||
| var html = converter.makeHtml(msg.content); | ||
| console.log(html); |
Copilot
AI
Sep 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Console.log statements should be removed from production code as they can expose user conversation content and clutter browser console output.
| console.log(html); |
| typingIndicatorContainer.remove(); | ||
|
|
||
| var html = converter.makeHtml(data.message); | ||
| console.log(html); |
Copilot
AI
Sep 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Console.log statements should be removed from production code as they can expose user conversation content and clutter browser console output.
| console.log(html); |
No description provided.