Skip to content

Commit

Permalink
Fix mysql2 wrapping
Browse files Browse the repository at this point in the history
  • Loading branch information
timokoessler committed Jan 3, 2025
1 parent ef592e3 commit e3ee11f
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 131 deletions.
71 changes: 64 additions & 7 deletions library/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@
"mongodb-v5": "npm:mongodb@^5.0.0",
"mongodb-v6": "npm:mongodb@^6.0.0",
"mysql": "^2.18.1",
"mysql2": "^3.10.0",
"mysql2-v3.10": "npm:[email protected]",
"mysql2-v3.12": "npm:[email protected]",
"needle": "^3.3.1",
"node-fetch": "^2",
"percentile": "^1.6.0",
Expand Down
114 changes: 0 additions & 114 deletions library/sinks/MySQL2.test.ts

This file was deleted.

164 changes: 164 additions & 0 deletions library/sinks/MySQL2.tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import * as t from "tap";
import { runWithContext, type Context } from "../agent/Context";
import { MySQL2 } from "./MySQL2";
import { startTestAgent } from "../helpers/startTestAgent";

export function createMySQL2Tests(versionPkgName: string) {

Check failure on line 6 in library/sinks/MySQL2.tests.ts

View workflow job for this annotation

GitHub Actions / lint (18.x)

Function 'createMySQL2Tests' has too many lines (145). Maximum allowed is 50
const dangerousContext: Context = {
remoteAddress: "::1",
method: "POST",
url: "http://localhost:4000",
query: {},
headers: {},
body: {
myTitle: `-- should be blocked`,
},
cookies: {},
routeParams: {},
source: "express",
route: "/posts/:id",
};

const safeContext: Context = {
remoteAddress: "::1",
method: "POST",
url: "http://localhost:4000/",
query: {},
headers: {},
body: {},
cookies: {},
routeParams: {},
source: "express",
route: "/posts/:id",
};

t.test("it detects SQL injections", async (t) => {

Check failure on line 35 in library/sinks/MySQL2.tests.ts

View workflow job for this annotation

GitHub Actions / lint (18.x)

Async arrow function has too many lines (117). Maximum allowed is 50
const agent = startTestAgent({
wrappers: [new MySQL2()],
rewrite: {
mysql2: versionPkgName,
},
});

const mysql = require(
`${versionPkgName}/promise`
) as typeof import("mysql2-v3.12/promise");

const connection = await mysql.createConnection({
host: "localhost",
user: "root",
password: "mypassword",
database: "catsdb",
port: 27015,
multipleStatements: true,
});

const mysqlCallback = require(
versionPkgName
) as typeof import("mysql2-v3.12");
const connection2 = mysqlCallback.createConnection({
host: "localhost",
user: "root",
password: "mypassword",
database: "catsdb",
port: 27015,
multipleStatements: true,
});

try {
await connection.query(
`
CREATE TABLE IF NOT EXISTS cats (
petname varchar(255)
);
`
);
await connection.execute("TRUNCATE cats");
const [rows] = await connection.query("SELECT petname FROM `cats`;");
t.same(rows, []);
const [moreRows] = await connection.query({
sql: "SELECT petname FROM `cats`",
});
t.same(moreRows, []);

const error = await t.rejects(async () => {
await runWithContext(dangerousContext, () => {
return connection.query("-- should be blocked");
});
});
if (error instanceof Error) {
t.same(
error.message,
"Zen has blocked an SQL injection: mysql2.query(...) originating from body.myTitle"
);
}

const error2 = await t.rejects(async () => {
await runWithContext(dangerousContext, () => {
return connection.query({ sql: "-- should be blocked" });
});
});
if (error2 instanceof Error) {
t.same(
error2.message,
"Zen has blocked an SQL injection: mysql2.query(...) originating from body.myTitle"
);
}

const undefinedQueryError = await t.rejects(async () => {
await runWithContext(dangerousContext, () => {
// @ts-expect-error Testing invalid args
return connection.query(undefined);
});
});

if (undefinedQueryError instanceof Error) {
t.same(
undefinedQueryError.message,
"Cannot read properties of undefined (reading 'constructor')"
);
}

await runWithContext(safeContext, () => {
return connection.query("-- This is a comment");
});

await runWithContext(safeContext, () => {
return connection.execute("SELECT 1");
});

const error3 = await t.rejects(async () => {
await runWithContext(dangerousContext, () => {
return new Promise((resolve, reject) => {
connection2.query(
"-- should be blocked",
(error: any, results: any) => {
if (error) {
reject(error);
} else {
resolve(results);
}
}
);
});
});
});
if (error3 instanceof Error) {
t.same(
error3.message,
"Zen has blocked an SQL injection: mysql2.query(...) originating from body.myTitle"
);
}

runWithContext(safeContext, () => {
connection2.query("-- This is a comment");
});
} catch (error: any) {
console.error(error);

Check failure on line 157 in library/sinks/MySQL2.tests.ts

View workflow job for this annotation

GitHub Actions / lint (18.x)

Unexpected console statement
t.fail(error);
} finally {
await connection.end();
await connection2.end();
}
});
}
Loading

0 comments on commit e3ee11f

Please sign in to comment.