Conversation
Add an AI assistant chatbot powered by Ozwell that can read and interact with any page in the application through a set of generic DOM tools. Architecture: - Server-side SSE proxy (routers/chatbot.js) with HMAC token auth so the browser never sees the real Ozwell API key. Includes a content filter that strips hallucinated JSON/function-call text from LLM responses. - Client-side tool handlers (chatbot-tools.js) that use a hybrid scraping approach: structured extraction for form fields (name/id/type/value) and raw innerText from <main> for everything else (tables, logs, buttons, headings). This lets the LLM see anything the user sees without needing per-element-type extractors. - Four tools: get_page_contents, set_page_contents, click_element (with 4-pass fuzzy matching), and submit_form. - Agent config (ozwell-agent.yaml) with anti-hallucination instructions. - Settings UI for configuring the Ozwell API URL and agent key. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tion The change handler for the template <select> was removing the name attribute when switching to 'custom', which meant the server never received template=custom in the POST body. Preserve name="template" so the server correctly resolves customTemplate as the image reference. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add table-layout:fixed and overflow-wrap:break-word so long domain names wrap instead of pushing the Actions column off-screen. Also set explicit column widths in the template. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
|
||
| function generateToken(userId, hmacKey) { | ||
| const payload = `${userId}:${Date.now()}`; | ||
| const hmac = crypto.createHmac('sha256', hmacKey).update(payload).digest('hex'); |
Check failure
Code scanning / CodeQL
Use of password hash with insufficient computational effort High
Copilot Autofix
AI 4 days ago
Copilot could not generate an autofix suggestion
Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.
| } | ||
| } | ||
|
|
||
| const response = await axios(axiosConfig); |
Check failure
Code scanning / CodeQL
Server-side request forgery Critical
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 days ago
In general, to fix this SSRF issue, we must ensure that user-controlled data do not arbitrarily influence the destination URL of server-side HTTP requests. Since the host and base path (apiUrl) are already server-controlled, the main concern here is the unvalidated path suffix derived from req.params.path. We should normalize and validate the requested subpath, enforcing an allow-list or at least blocking path traversal (..) and dangerous leading slashes, and ensure the resulting URL stays under an expected base path.
The best fix with minimal functional change is to sanitize subPath right after it is built and before constructing targetUrl. We can split the path into segments, reject any segment that is empty, ".", or "..", and then re-join them. If any invalid segment is detected, we immediately return a 400 response instead of proxying the request. This preserves the general behavior of proxying user paths to /v1/<subPath> while preventing traversal-style manipulation. Additionally, we should ensure that targetUrl is constructed using a proper URL join: new URL() with a base, to avoid surprises with extra slashes, but that is optional; we can still keep string concatenation if we only sanitize the segments.
Concretely, in create-a-container/routers/chatbot.js around lines 228–232, we will: (1) keep the existing extraction of pathSegments and subPath as the base behavior, (2) add a new block that sanitizes subPath by splitting on /, rejecting "", ".", "..", and rejoining valid segments, and (3) use this sanitized string (safeSubPath) when building targetUrl. If an invalid segment is encountered, we respond with 400 Invalid path and do not call axios. No new external dependencies are required; we can implement this sanitization with basic JavaScript string and array operations.
| @@ -228,8 +228,20 @@ | ||
| // path-to-regexp 8.x returns wildcard as an array of segments | ||
| const pathSegments = req.params.path || []; | ||
| const subPath = Array.isArray(pathSegments) ? pathSegments.join('/') : pathSegments; | ||
| const targetUrl = `${apiUrl}/v1/${subPath}`; | ||
|
|
||
| // Sanitize subPath to prevent path traversal and SSRF-style abuse | ||
| const rawSegments = String(subPath || '').split('/'); | ||
| const safeSegments = []; | ||
| for (const segment of rawSegments) { | ||
| // Disallow empty, current-dir, or parent-dir segments | ||
| if (!segment || segment === '.' || segment === '..') { | ||
| return res.status(400).json({ error: 'Invalid path' }); | ||
| } | ||
| safeSegments.push(segment); | ||
| } | ||
| const safeSubPath = safeSegments.join('/'); | ||
| const targetUrl = `${apiUrl}/v1/${safeSubPath}`; | ||
|
|
||
| const axiosConfig = { | ||
| method: req.method, | ||
| url: targetUrl, |
No description provided.