Skip to content

Commit 89742b0

Browse files
committed
feat(eval): expand async and supply-chain fixture packs
Add new supply-chain cases for typosquats, unpinned dependencies, version downgrades, and go replace directives, plus new async cases for blocking runtime calls, nested event loops, and cancel ordering with checked-in pack tests.
1 parent e0b50c6 commit 89742b0

File tree

3 files changed

+366
-2
lines changed

3 files changed

+366
-2
lines changed

eval/fixtures/deep_review_suite/review_depth_async.json

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
"description": "Async-correctness benchmark pack for deeper live review runs.",
66
"languages": [
77
"rust",
8-
"typescript"
8+
"typescript",
9+
"python",
10+
"go"
911
],
1012
"categories": [
1113
"bug",
@@ -142,7 +144,8 @@
142144
],
143145
"tags_any": [
144146
"async"
145-
]
147+
],
148+
"rule_id": "bug.async.foreach-no-await"
146149
}
147150
],
148151
"negative_findings": [
@@ -155,6 +158,108 @@
155158
"max_total": 8,
156159
"description": "Notification fan-out should keep awaiting all spawned async work.",
157160
"source": "deep-review-suite"
161+
},
162+
{
163+
"name": "rust-blocking-in-async-runtime",
164+
"category": "bug",
165+
"language": "rust",
166+
"difficulty": "Hard",
167+
"diff_content": "diff --git a/src/cache.rs b/src/cache.rs\nindex 1111111..2222222 100644\n--- a/src/cache.rs\n+++ b/src/cache.rs\n@@ -1,5 +1,7 @@\n pub async fn warm_cache(path: &str) -> anyhow::Result<String> {\n- tokio::fs::read_to_string(path).await.map_err(Into::into)\n+ tokio::spawn(async move {\n+ std::fs::read_to_string(path).unwrap()\n+ }).await.unwrap();\n+ Ok(String::new())\n }\n",
168+
"expected_findings": [
169+
{
170+
"description": "Blocking filesystem I/O is performed inside async runtime work instead of using Tokio's async APIs or spawn_blocking.",
171+
"severity": "Warning",
172+
"category": "Bug",
173+
"file_pattern": "src/cache.rs",
174+
"line_hint": 3,
175+
"contains_any": [
176+
"blocking call in async context",
177+
"std::fs::read_to_string",
178+
"blocks the async runtime",
179+
"use spawn_blocking",
180+
"use tokio::fs"
181+
],
182+
"rule_id": "bug.async.blocking-runtime-call"
183+
}
184+
],
185+
"negative_findings": [
186+
{
187+
"description": "Avoid style-only comments.",
188+
"contains": "style"
189+
}
190+
],
191+
"min_total": 1,
192+
"max_total": 8,
193+
"description": "Async Rust code should avoid blocking std::fs work on runtime threads.",
194+
"source": "deep-review-suite"
195+
},
196+
{
197+
"name": "python-asyncio-run-in-running-loop",
198+
"category": "bug",
199+
"language": "python",
200+
"difficulty": "Medium",
201+
"diff_content": "diff --git a/app/tasks.py b/app/tasks.py\nindex 1111111..2222222 100644\n--- a/app/tasks.py\n+++ b/app/tasks.py\n@@ -1,5 +1,5 @@\n async def refresh_reports():\n- await sync_reports()\n+ asyncio.run(sync_reports())\n return {\"ok\": True}\n",
202+
"expected_findings": [
203+
{
204+
"description": "asyncio.run is called from inside an async function where an event loop is already running.",
205+
"severity": "Warning",
206+
"category": "Bug",
207+
"file_pattern": "app/tasks.py",
208+
"line_hint": 2,
209+
"contains_any": [
210+
"asyncio.run",
211+
"already running event loop",
212+
"nested event loop",
213+
"runtimeerror",
214+
"should await the coroutine directly"
215+
],
216+
"rule_id": "bug.async.nested-event-loop"
217+
}
218+
],
219+
"negative_findings": [
220+
{
221+
"description": "Avoid style-only comments.",
222+
"contains": "style"
223+
}
224+
],
225+
"min_total": 1,
226+
"max_total": 8,
227+
"description": "Python async functions should not start a fresh event loop with asyncio.run.",
228+
"source": "deep-review-suite"
229+
},
230+
{
231+
"name": "go-context-cancel-defer-order",
232+
"category": "bug",
233+
"language": "go",
234+
"difficulty": "Medium",
235+
"diff_content": "diff --git a/service/worker.go b/service/worker.go\nindex 1111111..2222222 100644\n--- a/service/worker.go\n+++ b/service/worker.go\n@@ -1,7 +1,8 @@\n func StartWorker(parent context.Context) error {\n ctx, cancel := context.WithTimeout(parent, time.Second)\n go runWorker(ctx)\n- defer cancel()\n+ cancel()\n+ defer cancel()\n return nil\n }\n",
236+
"expected_findings": [
237+
{
238+
"description": "Context is canceled immediately after spawning the goroutine, so the worker may observe a canceled context before it starts useful work.",
239+
"severity": "Warning",
240+
"category": "Bug",
241+
"file_pattern": "service/worker.go",
242+
"line_hint": 4,
243+
"contains_any": [
244+
"context canceled too early",
245+
"goroutine may start with a canceled context",
246+
"premature cancel",
247+
"cancel is invoked immediately",
248+
"defer cancel"
249+
],
250+
"rule_id": "bug.async.context-cancel-order"
251+
}
252+
],
253+
"negative_findings": [
254+
{
255+
"description": "Avoid style-only comments.",
256+
"contains": "style"
257+
}
258+
],
259+
"min_total": 1,
260+
"max_total": 8,
261+
"description": "Go concurrency code should not cancel shared contexts before spawned work has a chance to run.",
262+
"source": "deep-review-suite"
158263
}
159264
]
160265
}

eval/fixtures/deep_review_suite/review_depth_supply_chain.json

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
"version": "1.0.0",
55
"description": "Supply-chain and dependency trust benchmark pack for deeper live review runs.",
66
"languages": [
7+
"typescript",
8+
"python",
9+
"rust",
10+
"go",
711
"yaml",
812
"docker"
913
],
@@ -163,6 +167,145 @@
163167
"max_total": 8,
164168
"description": "CI workflows should not combine pull_request_target with attacker-controlled shell input.",
165169
"source": "deep-review-suite"
170+
},
171+
{
172+
"name": "npm-typosquat-package",
173+
"category": "security",
174+
"language": "typescript",
175+
"difficulty": "Medium",
176+
"diff_content": "diff --git a/package.json b/package.json\nindex 1111111..2222222 100644\n--- a/package.json\n+++ b/package.json\n@@ -5,5 +5,6 @@\n \"dependencies\": {\n \"express\": \"^4.19.2\",\n- \"lodash\": \"^4.17.21\"\n+ \"lodash\": \"^4.17.21\",\n+ \"lodahs\": \"^4.17.21\"\n }\n }\n",
177+
"expected_findings": [
178+
{
179+
"description": "New dependency name looks like a typosquat of lodash.",
180+
"severity": "Warning",
181+
"category": "Security",
182+
"file_pattern": "package.json",
183+
"line_hint": 7,
184+
"contains_any": [
185+
"typosquat",
186+
"typosquatting",
187+
"suspicious package name",
188+
"lodahs",
189+
"looks like lodash"
190+
],
191+
"tags_any": [
192+
"typosquatting",
193+
"supply-chain"
194+
],
195+
"rule_id": "sec.supply-chain.new-dependency"
196+
}
197+
],
198+
"negative_findings": [
199+
{
200+
"description": "Avoid style-only comments.",
201+
"contains": "style"
202+
}
203+
],
204+
"min_total": 1,
205+
"max_total": 8,
206+
"description": "Review newly added dependencies for typo-squatting and other supply-chain red flags.",
207+
"source": "deep-review-suite"
208+
},
209+
{
210+
"name": "python-unpinned-dependency",
211+
"category": "security",
212+
"language": "python",
213+
"difficulty": "Easy",
214+
"diff_content": "diff --git a/requirements.txt b/requirements.txt\nindex 1111111..2222222 100644\n--- a/requirements.txt\n+++ b/requirements.txt\n@@ -1,2 +1,3 @@\n flask==3.0.3\n sqlalchemy==2.0.36\n+requests\n",
215+
"expected_findings": [
216+
{
217+
"description": "Dependency is added without a pinned version.",
218+
"severity": "Info",
219+
"category": "Security",
220+
"file_pattern": "requirements.txt",
221+
"line_hint": 3,
222+
"contains_any": [
223+
"unpinned dependency",
224+
"pin to a specific version",
225+
"requests without version",
226+
"loosely pinned dependency"
227+
],
228+
"rule_id": "sec.supply-chain.unpinned-version"
229+
}
230+
],
231+
"negative_findings": [
232+
{
233+
"description": "Avoid style-only comments.",
234+
"contains": "style"
235+
}
236+
],
237+
"min_total": 1,
238+
"max_total": 8,
239+
"description": "Requirements files should pin newly introduced packages to exact or tightly controlled versions.",
240+
"source": "deep-review-suite"
241+
},
242+
{
243+
"name": "rust-yanked-crate-version",
244+
"category": "security",
245+
"language": "rust",
246+
"difficulty": "Hard",
247+
"diff_content": "diff --git a/Cargo.toml b/Cargo.toml\nindex 1111111..2222222 100644\n--- a/Cargo.toml\n+++ b/Cargo.toml\n@@ -8,5 +8,5 @@ edition = \"2021\"\n [dependencies]\n anyhow = \"1\"\n-time = \"0.3.36\"\n+time = \"=0.1.43\" # downgrade to an old yanked release from a previous incident postmortem\n tokio = { version = \"1\", features = [\"full\"] }\n",
248+
"expected_findings": [
249+
{
250+
"description": "Dependency is downgraded to an old yanked or known-bad crate version.",
251+
"severity": "Warning",
252+
"category": "Security",
253+
"file_pattern": "Cargo.toml",
254+
"line_hint": 4,
255+
"contains_any": [
256+
"old yanked version",
257+
"downgrade to an older version",
258+
"known bad version",
259+
"version downgrade",
260+
"time = \"=0.1.43\""
261+
],
262+
"rule_id": "sec.supply-chain.version-downgrade"
263+
}
264+
],
265+
"negative_findings": [
266+
{
267+
"description": "Avoid style-only comments.",
268+
"contains": "style"
269+
}
270+
],
271+
"min_total": 1,
272+
"max_total": 8,
273+
"description": "Dependency downgrades to suspiciously old or yanked releases should be treated as supply-chain risk.",
274+
"source": "deep-review-suite"
275+
},
276+
{
277+
"name": "go-replace-directive-remote",
278+
"category": "security",
279+
"language": "go",
280+
"difficulty": "Medium",
281+
"diff_content": "diff --git a/go.mod b/go.mod\nindex 1111111..2222222 100644\n--- a/go.mod\n+++ b/go.mod\n@@ -3,3 +3,4 @@ module example.com/payments\n go 1.22\n require github.com/gorilla/mux v1.8.1\n+replace github.com/gorilla/mux => corp.example.com/forks/mux v1.8.1\n",
282+
"expected_findings": [
283+
{
284+
"description": "go.mod replace directive redirects module resolution to a non-standard remote source.",
285+
"severity": "Warning",
286+
"category": "Security",
287+
"file_pattern": "go.mod",
288+
"line_hint": 4,
289+
"contains_any": [
290+
"replace directive",
291+
"redirects module resolution",
292+
"non-standard remote module path",
293+
"suspicious go.mod replace",
294+
"override dependency source"
295+
],
296+
"rule_id": "sec.supply-chain.override-directive"
297+
}
298+
],
299+
"negative_findings": [
300+
{
301+
"description": "Avoid style-only comments.",
302+
"contains": "style"
303+
}
304+
],
305+
"min_total": 1,
306+
"max_total": 8,
307+
"description": "Module replacement directives should be scrutinized because they bypass the normal upstream source of a dependency.",
308+
"source": "deep-review-suite"
166309
}
167310
]
168311
}

0 commit comments

Comments
 (0)