Skip to content

Commit 99acd8c

Browse files
authored
chore(detectors): Prevent Query Injection detector from running on SQL queries (#96690)
fixes an edge case where some oddly formed SQL requests were getting picked up by the query injection detector (not the sql injection one)
1 parent f6ba382 commit 99acd8c

File tree

3 files changed

+171
-0
lines changed

3 files changed

+171
-0
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
{
2+
"event_id": "5d6401994d7949d2ac3474f472564370",
3+
"platform": "node",
4+
"message": "",
5+
"datetime": "2025-05-12T22:42:38.642986+00:00",
6+
"breakdowns": {
7+
"span_ops": {
8+
"ops.db": {
9+
"value": 65.715075,
10+
"unit": "millisecond"
11+
},
12+
"total.time": {
13+
"value": 67.105293,
14+
"unit": "millisecond"
15+
}
16+
}
17+
},
18+
"request": {
19+
"url": "http://localhost:3001/vulnerable-login",
20+
"method": "GET",
21+
"query_string": [["where", {}]]
22+
},
23+
"modules": {
24+
"sequelize": "1.0.0"
25+
},
26+
"spans": [
27+
{
28+
"timestamp": 1747089758.567536,
29+
"start_timestamp": 1747089758.567,
30+
"exclusive_time": 0.536203,
31+
"op": "middleware.express",
32+
"span_id": "4a06692f4abc8dbe",
33+
"parent_span_id": "91fa92ff0205967d",
34+
"trace_id": "375a86eca09a4a4e91903838dd771f50",
35+
"status": "ok",
36+
"description": "corsMiddleware",
37+
"origin": "auto.http.otel.express",
38+
"data": {
39+
"express.name": "corsMiddleware",
40+
"express.type": "middleware",
41+
"sentry.op": "middleware.express",
42+
"sentry.origin": "auto.http.otel.express"
43+
},
44+
"sentry_tags": {
45+
"user": "ip:::1",
46+
"user.ip": "::1",
47+
"environment": "production",
48+
"transaction": "GET /vulnerable-login",
49+
"transaction.method": "GET",
50+
"transaction.op": "http.server",
51+
"browser.name": "Chrome",
52+
"sdk.name": "sentry.javascript.node",
53+
"sdk.version": "9.17.0",
54+
"platform": "node",
55+
"os.name": "macOS",
56+
"category": "middleware",
57+
"op": "middleware.express",
58+
"status": "ok",
59+
"trace.status": "ok"
60+
},
61+
"hash": "e6088cf8b370ed60"
62+
},
63+
{
64+
"timestamp": 1747089758.568761,
65+
"start_timestamp": 1747089758.568,
66+
"exclusive_time": 0.761032,
67+
"op": "middleware.express",
68+
"span_id": "92553d2584d250b8",
69+
"parent_span_id": "91fa92ff0205967d",
70+
"trace_id": "375a86eca09a4a4e91903838dd771f50",
71+
"status": "ok",
72+
"description": "jsonParser",
73+
"origin": "auto.http.otel.express",
74+
"data": {
75+
"express.name": "jsonParser",
76+
"express.type": "middleware",
77+
"sentry.op": "middleware.express",
78+
"sentry.origin": "auto.http.otel.express"
79+
},
80+
"sentry_tags": {
81+
"user": "ip:::1",
82+
"user.ip": "::1",
83+
"environment": "production",
84+
"transaction": "GET /vulnerable-login",
85+
"transaction.method": "GET",
86+
"transaction.op": "http.server",
87+
"browser.name": "Chrome",
88+
"sdk.name": "sentry.javascript.node",
89+
"sdk.version": "9.17.0",
90+
"platform": "node",
91+
"os.name": "macOS",
92+
"category": "middleware",
93+
"op": "middleware.express",
94+
"status": "ok",
95+
"trace.status": "ok"
96+
},
97+
"hash": "c81e963dad9ebc6c"
98+
},
99+
{
100+
"timestamp": 1747089758.569093,
101+
"start_timestamp": 1747089758.569,
102+
"exclusive_time": 0.092983,
103+
"op": "request_handler.express",
104+
"span_id": "435146ab0909419d",
105+
"parent_span_id": "91fa92ff0205967d",
106+
"trace_id": "375a86eca09a4a4e91903838dd771f50",
107+
"status": "ok",
108+
"description": "/vulnerable-login",
109+
"origin": "auto.http.otel.express",
110+
"data": {
111+
"express.name": "/vulnerable-login",
112+
"express.type": "request_handler",
113+
"http.route": "/vulnerable-login",
114+
"sentry.op": "request_handler.express",
115+
"sentry.origin": "auto.http.otel.express"
116+
},
117+
"sentry_tags": {
118+
"user": "ip:::1",
119+
"user.ip": "::1",
120+
"environment": "production",
121+
"transaction": "GET /vulnerable-login",
122+
"transaction.method": "GET",
123+
"transaction.op": "http.server",
124+
"browser.name": "Chrome",
125+
"sdk.name": "sentry.javascript.node",
126+
"sdk.version": "9.17.0",
127+
"platform": "node",
128+
"os.name": "macOS",
129+
"op": "request_handler.express",
130+
"status": "ok",
131+
"trace.status": "ok"
132+
},
133+
"hash": "872b0c84a6f1c590"
134+
},
135+
{
136+
"timestamp": 1747089758.637715,
137+
"start_timestamp": 1747089758.572,
138+
"exclusive_time": 65.715075,
139+
"op": "db",
140+
"span_id": "4703181ac343f71a",
141+
"parent_span_id": "91fa92ff0205967d",
142+
"trace_id": "375a86eca09a4a4e91903838dd771f50",
143+
"status": "ok",
144+
"description": "SELECT * FROM users WHERE username = ? ORDER BY username ASC",
145+
"origin": "auto.db.otel.mysql2",
146+
"data": {
147+
"db.system": "mysql",
148+
"db.connection_string": "jdbc:mysql://localhost:3306/injection_test",
149+
"db.name": "injection_test",
150+
"db.statement": "SELECT * FROM users WHERE username = ? ORDER BY username ASC",
151+
"db.user": "root",
152+
"net.peer.name": "localhost",
153+
"net.peer.port": 3306,
154+
"otel.kind": "CLIENT",
155+
"sentry.op": "db",
156+
"sentry.origin": "auto.db.otel.mysql2"
157+
},
158+
"hash": "45330ba0cafa5997"
159+
}
160+
]
161+
}

src/sentry/performance_issues/detectors/query_injection_detector.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,14 @@ def is_span_eligible(cls, span: Span) -> bool:
131131
return False
132132

133133
description = span.get("description", None)
134+
134135
if not description:
135136
return False
137+
138+
sql_keywords = ("SELECT", "UPDATE", "INSERT")
139+
if any(description.upper().startswith(keyword) for keyword in sql_keywords):
140+
return False
141+
136142
return True
137143

138144
def _fingerprint(self, description: str) -> str:

tests/sentry/performance_issues/test_query_injection_detector.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,7 @@ def test_query_injection_detection_in_query_params(self) -> None:
4343
assert problem.evidence_data is not None
4444
assert problem.evidence_data["vulnerable_parameters"] == [("username", {"$ne": None})]
4545
assert problem.evidence_data["request_url"] == "http://localhost:3000/login"
46+
47+
def test_query_injection_detection_on_sql_query(self) -> None:
48+
injection_event = get_event("query-injection/query-injection-sql-query")
49+
assert len(self.find_problems(injection_event)) == 0

0 commit comments

Comments
 (0)