Skip to content

Commit 8b2c14c

Browse files
security: fix MEDIUM findings (M2, M5, M10) and H5 (#5601)
* security: fix MEDIUM findings (M2, M5, M10) and HIGH H5 M2: Validate table name and where field in buildDynamicUpdateQuery() against safe identifier regex to prevent SQL injection. M5: Add URL protocol validation in hypothesisRunner to prevent SSRF. Only allows http: and https: protocols. M10: Replace Math.random() with crypto.randomBytes() for prompt ID generation in PromptManager. H5: Replace eval() with direct function call in requests.tsx. The Google Translate compatibility fix was using eval() on a hardcoded string — converted to a proper function. * revert: undo M10 crypto.randomBytes change in PromptManager Math.random() is fine for prompt IDs — they're not security tokens.
1 parent 4c20bb7 commit 8b2c14c

File tree

3 files changed

+32
-21
lines changed

3 files changed

+32
-21
lines changed

valhalla/jawn/src/lib/experiment/hypothesisRunner.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ async function runWithRetry(
3333
promptVersionId,
3434
isOriginalRequest,
3535
} = props;
36+
// Validate URL to prevent SSRF
37+
if (!["https:", "http:"].includes(url.protocol)) {
38+
return err(`Invalid URL protocol: ${url.protocol}`);
39+
}
40+
3641
const heliconeOnHeliconeApiKey = await GET_KEY(
3742
"key:helicone_on_helicone_key"
3843
);

web/lib/api/db/dbExecute.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,15 @@ export function buildDynamicUpdateQuery(options: {
149149
};
150150
}): { query: string; params: any[] } {
151151
const { from, set, where } = options;
152+
153+
// Validate table and field names to prevent SQL injection
154+
if (!/^[a-zA-Z0-9_]+$/.test(from)) {
155+
throw new Error(`Invalid table name: ${from}`);
156+
}
157+
if (!/^[a-zA-Z0-9_]+$/.test(where.field)) {
158+
throw new Error(`Invalid where field name: ${where.field}`);
159+
}
160+
152161
const queryParts: string[] = [];
153162
const params: any[] = [];
154163
let paramCounter = 1;

web/pages/requests.tsx

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,28 @@ import { SortDirection } from "../services/lib/sorts/requests/sorts";
66
import { logger } from "@/lib/telemetry/logger";
77

88
// Got this ugly hack from https://stackoverflow.com/questions/21926083/failed-to-execute-removechild-on-node
9-
const jsToRun = `
10-
if (typeof Node === 'function' && Node.prototype) {
11-
const originalRemoveChild = Node.prototype.removeChild;
12-
Node.prototype.removeChild = function(child) {
13-
if (child.parentNode !== this) {
14-
if (console) {
15-
logger.error({ child: child.toString(), parent: this.toString() }, 'Cannot remove a child from a different parent');
9+
function applyGoogleTranslateFix() {
10+
if (typeof Node === "function" && Node.prototype) {
11+
const originalRemoveChild = Node.prototype.removeChild;
12+
Node.prototype.removeChild = function (child: any) {
13+
if (child.parentNode !== this) {
14+
return child;
1615
}
17-
return child;
18-
}
19-
return originalRemoveChild.apply(this, arguments);
20-
}
16+
return originalRemoveChild.apply(this, arguments as any);
17+
};
2118

22-
const originalInsertBefore = Node.prototype.insertBefore;
23-
Node.prototype.insertBefore = function(newNode, referenceNode) {
24-
if (referenceNode && referenceNode.parentNode !== this) {
25-
if (console) {
26-
logger.error({ referenceNode: referenceNode.toString(), parent: this.toString() }, 'Cannot insert before a reference node from a different parent');
19+
const originalInsertBefore = Node.prototype.insertBefore;
20+
Node.prototype.insertBefore = function (
21+
newNode: any,
22+
referenceNode: any
23+
) {
24+
if (referenceNode && referenceNode.parentNode !== this) {
25+
return newNode;
2726
}
28-
return newNode;
29-
}
30-
return originalInsertBefore.apply(this, arguments);
27+
return originalInsertBefore.apply(this, arguments as any);
28+
};
3129
}
3230
}
33-
`;
3431

3532
interface RequestsV2Props {
3633
currentPage: number;
@@ -49,7 +46,7 @@ const RequestsV2 = (props: RequestsV2Props) => {
4946
useEffect(() => {
5047
var observer = new MutationObserver(function () {
5148
if (document.documentElement.className.match("translated")) {
52-
eval(jsToRun);
49+
applyGoogleTranslateFix();
5350
} else {
5451
logger.info("Page untranslate");
5552
}

0 commit comments

Comments
 (0)