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