[SCAL-320445] changes for eureka object search tools#175
Conversation
⛔ Snyk checks have failed. 2 issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
| ctx.setChosenInstanceUrl(sanitized); | ||
|
|
||
| res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }); | ||
| res.end(renderManualPage(sanitized)); |
There was a problem hiding this comment.
Cross-site Scripting (XSS)
Unsanitized input from the request URL flows into end, where it is used to render an HTML page returned to the user. This may result in a Cross-Site Scripting attack (XSS).
Line 158 | CWE-79 | Priority score 817 | Learn more about this vulnerability
Data flow: 19 steps
Step 1 - 6
mcp-server/src/local-auth/sso-login.ts
Line 222 in eb99754
Step 7 - 13 src/local-auth/sso-login.ts#L223
Step 14 - 15 src/local-auth/sso-login.ts#L225
Step 16 src/local-auth/sso-login.ts#L151
Step 17 - 19
mcp-server/src/local-auth/sso-login.ts
Line 158 in eb99754
⚡ Refresh the page to see if a fix suggestion is available 🔄
There was a problem hiding this comment.
⚡ Snyk Agent Fix suggestion 1 of 1
The diff introduces hostile URL origin validation to the code, updating the manual URL after sanitization to include the origin part of the sanitized URL. This checks to ensure that the URL begins with either http:// or https:// and includes characters only allowed in a URL. If the URL fails this check, the server responds with a 400 Bad Request, indicating an invalid URL. This helps prevent instances where dangerous or invalid URLs could somehow be passed as parameters and potentially cause harm, especially if the endpoint at that URL is vulnerable. generated by AI
Code changes
--- src/local-auth/sso-login.ts
+++ src/local-auth/sso-login.ts
@@ -154,8 +154,14 @@
}
ctx.setChosenInstanceUrl(sanitized);
+ const origin = new URL(sanitized).origin;
+ if (!/^https?:\/\/[A-Za-z0-9.\-]+(?::[0-9]+)?$/.test(origin)) {
+ res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
+ res.end(renderInstancePage("", "Invalid cluster URL"));
+ return;
+ }
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
- res.end(renderManualPage(sanitized));
+ res.end(renderManualPage(origin));
return;
}
Content generated by AI, expires on 2026-07-06 13:57:09 UTC. Refresh the page after running Snyk commands.
Commands
- ✅ To apply this fix and create a commit - reply with
@snyk /apply 1
| return; | ||
| } | ||
| res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }); | ||
| res.end(renderCallbackPage(instanceUrl)); |
There was a problem hiding this comment.
Cross-site Scripting (XSS)
Unsanitized input from the request URL flows into end, where it is used to render an HTML page returned to the user. This may result in a Cross-Site Scripting attack (XSS).
Line 185 | CWE-79 | Priority score 817 | Learn more about this vulnerability
Data flow: 19 steps
Step 1 - 6
mcp-server/src/local-auth/sso-login.ts
Line 124 in eb99754
Step 7 - 13 src/local-auth/sso-login.ts#L170
Step 14 - 16 src/local-auth/sso-login.ts#L172
Step 17 - 19
mcp-server/src/local-auth/sso-login.ts
Line 185 in eb99754
⚡ Refresh the page to see if a fix suggestion is available 🔄
There was a problem hiding this comment.
⚡ Snyk Agent Fix suggestion 1 of 1
The diff introduces a regular expression check to validate the format of instanceUrl. It ensures that the URL starts with http:// or https://, followed by any alphanumeric characters, dots, or hyphens, and optionally includes a domain and a port. If the URL does not match this pattern, the server responds with a 400 Bad Request status and a custom error message Invalid cluster URL; please start over., thus preventing potential abuse of the service by providing incorrect URLs and avoiding exposure to further security risks like directory traversal attacks or unauthorized access. generated by AI
Code changes
--- src/local-auth/sso-login.ts
+++ src/local-auth/sso-login.ts
@@ -181,6 +181,13 @@
);
return;
}
+ if (!/^https?:\/\/[a-zA-Z0-9.\-]+(?::\d+)?\/?$/.test(instanceUrl)) {
+ res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
+ res.end(
+ renderInstancePage("", "Invalid cluster URL; please start over."),
+ );
+ return;
+ }
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
res.end(renderCallbackPage(instanceUrl));
return;
Content generated by AI, expires on 2026-07-06 13:56:55 UTC. Refresh the page after running Snyk commands.
Commands
- ✅ To apply this fix and create a commit - reply with
@snyk /apply 1
There was a problem hiding this comment.
Code Review
This pull request introduces interactive SSO login capabilities via a loopback HTTP server and adds Eureka-backed object search (search_objects) and data fetching (fetch_data) tools to the MCP server, complete with terminology mapping and feature-flag gating. Review feedback highlights critical security improvements to prevent XSS by escaping tokenUrl in HTML templates, as well as code robustness enhancements in data fetching to guard against runtime TypeErrors and avoid mutating input objects.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const tokenUrl = buildTokenFetchUrl(base); | ||
| const safeBase = escapeHtml(base); |
There was a problem hiding this comment.
| <h2>Manual sign-in</h2> | ||
| <ol> | ||
| <li>Make sure you are signed in to <a href="${safeBase}" target="_blank" rel="noopener">${safeBase}</a> (open it and log in if needed).</li> | ||
| <li>Open the <a id="token-link" href="${tokenUrl}" target="_blank" rel="noopener">token page</a> and copy the entire response.</li> |
There was a problem hiding this comment.
Use the escaped safeTokenUrl instead of the raw tokenUrl in the href attribute.
| <li>Open the <a id="token-link" href="${tokenUrl}" target="_blank" rel="noopener">token page</a> and copy the entire response.</li> | |
| <li>Open the <a id="token-link" href="${safeTokenUrl}" target="_blank" rel="noopener">token page</a> and copy the entire response.</li> |
| * fetch is blocked. | ||
| */ | ||
| export function renderCallbackPage(base: string): string { | ||
| const tokenUrl = buildTokenFetchUrl(base); |
| <p id="status">Retrieving your authentication token…</p> | ||
| <div id="manual"> | ||
| <p class="error">Could not retrieve the token automatically (your cluster may block this).</p> | ||
| <p>Open <a id="token-link" href="${tokenUrl}" target="_blank" rel="noopener">this link</a>, copy the full response, and paste it below.</p> |
There was a problem hiding this comment.
Use the escaped safeTokenUrl instead of the raw tokenUrl in the href attribute of the link.
| <p>Open <a id="token-link" href="${tokenUrl}" target="_blank" rel="noopener">this link</a>, copy the full response, and paste it below.</p> | |
| <p>Open <a id="token-link" href="${safeTokenUrl}" target="_blank" rel="noopener">this link</a>, copy the full response, and paste it below.</p> |
| function roundRow(row: unknown[]): unknown[] { | ||
| return row.map(roundCell); | ||
| } |
There was a problem hiding this comment.
If rawRows contains null or undefined elements (as implied by the .find(r => r != null) check on line 66), calling roundRow on a non-array value will throw a TypeError at runtime. Guard roundRow by ensuring the input is an array before calling .map.
| function roundRow(row: unknown[]): unknown[] { | |
| return row.map(roundCell); | |
| } | |
| function roundRow(row: unknown): unknown[] { | |
| if (!Array.isArray(row)) { | |
| return []; | |
| } | |
| return row.map(roundCell); | |
| } |
|
|
||
| // FULL: object rows. Prefer the server's column ordering when present, | ||
| // otherwise derive it from the union of keys (first-seen order). | ||
| const columns = content.column_names ?? []; |
There was a problem hiding this comment.
No description provided.