@@ -20,12 +20,53 @@ import {
2020} from "@jazzer.js/core" ;
2121import { callSiteId , registerBeforeHook } from "@jazzer.js/hooking" ;
2222
23+ import { bugDetectorConfigurations } from "../configuration" ;
24+
25+ import {
26+ buildGenericSuppressionSnippet ,
27+ captureStack ,
28+ getUserFacingStackLines ,
29+ IgnoreList ,
30+ type IgnoreRule ,
31+ } from "../shared/finding-suppression" ;
32+
2333/**
2434 * Importing this file adds "before-hooks" for all functions in the built-in `fs`, `fs/promises`, and `path` module and guides
2535 * the fuzzer towards the uniquely chosen `goal` string `"../../jaz_zer"`. If the goal is found in the first argument
2636 * of any hooked function, a `Finding` is reported.
2737 */
2838const goal = "../../jaz_zer" ;
39+
40+ export type { IgnoreRule } from "../shared/finding-suppression" ;
41+
42+ /**
43+ * Configuration for the Path Traversal bug detector.
44+ * Controls suppression of matched path traversal findings.
45+ */
46+ export interface PathTraversalConfig {
47+ /**
48+ * Suppresses findings that match the provided rule.
49+ * Use this to silence known-safe callsites in your test environment.
50+ */
51+ ignore ( rule : IgnoreRule ) : this;
52+ }
53+
54+ class PathTraversalConfigImpl implements PathTraversalConfig {
55+ private readonly _ignoredRules = new IgnoreList ( ) ;
56+
57+ ignore ( rule : IgnoreRule ) : this {
58+ this . _ignoredRules . add ( rule ) ;
59+ return this ;
60+ }
61+
62+ shouldReport ( stack : string ) : boolean {
63+ return ! this . _ignoredRules . matches ( stack ) ;
64+ }
65+ }
66+
67+ const config = new PathTraversalConfigImpl ( ) ;
68+ bugDetectorConfigurations . set ( "path-traversal" , config ) ;
69+
2970const modulesToHook = [
3071 {
3172 moduleName : "fs" ,
@@ -208,11 +249,38 @@ function detectFindingAndGuideFuzzing(
208249 ) {
209250 const argument = input . toString ( ) ;
210251 if ( argument . includes ( goal ) ) {
252+ const stack = captureStack ( ) ;
253+ if ( ! config . shouldReport ( stack ) ) {
254+ return ;
255+ }
211256 reportAndThrowFinding (
212- "Path Traversal\n" +
213- ` in ${ functionName } (): called with ' ${ argument } '` ,
257+ buildFindingMessage ( functionName , argument , stack ) ,
258+ false ,
214259 ) ;
215260 }
216261 guideTowardsContainment ( argument , goal , hookId ) ;
217262 }
218263}
264+
265+ function buildFindingMessage (
266+ functionName : string ,
267+ argument : string ,
268+ stack : string ,
269+ ) : string {
270+ const relevantStackLines = getUserFacingStackLines ( stack ) ;
271+ const message = [
272+ "Path Traversal" ,
273+ ` in ${ functionName } (): called with '${ argument } '` ,
274+ ] ;
275+ if ( relevantStackLines . length > 0 ) {
276+ message . push ( ...relevantStackLines ) ;
277+ }
278+ message . push (
279+ "" ,
280+ "[!] If this callsite is expected in your test environment, suppress it:" ,
281+ " Example only: copy/paste it and adapt `stackPattern` to your needs." ,
282+ "" ,
283+ buildGenericSuppressionSnippet ( "path-traversal" , "ignore" ) ,
284+ ) ;
285+ return message . join ( "\n" ) ;
286+ }
0 commit comments