@@ -8,16 +8,19 @@ import {
88 getCallExpressionIdentifier ,
99 getCallExpressionArguments ,
1010 getVariableDeclarationIdentifiers ,
11- extractLogicalExpression
11+ extractLogicalExpression ,
12+ isLiteral
1213} from "@nodesecure/estree-ast-utils" ;
14+ import { match } from "ts-pattern" ;
1315
1416// Import Internal Dependencies
1517import {
1618 notNullOrUndefined ,
1719 isEvilIdentifierPath ,
1820 isNeutralCallable ,
1921 getSubMemberExpressionSegments ,
20- makePrefixRemover
22+ makePrefixRemover ,
23+ stripNodePrefix
2124} from "./utils/index.js" ;
2225
2326// CONSTANTS
@@ -36,7 +39,6 @@ const kRequirePatterns = new Set([
3639 "process.mainModule.require" ,
3740 "process.getBuiltinModule"
3841] ) ;
39- const kNodeModulePrefix = "node:" ;
4042const kUnsafeGlobalCallExpression = new Set ( [ "eval" , "Function" ] ) ;
4143
4244export interface DataIdentifierOptions {
@@ -276,6 +278,29 @@ export class VariableTracer extends EventEmitter {
276278 }
277279 }
278280
281+ #reverseAtob(
282+ node : ESTree . CallExpression ,
283+ id : ESTree . Identifier
284+ ) {
285+ const callExprArguments = getCallExpressionArguments (
286+ node ,
287+ {
288+ externalIdentifierLookup : ( name ) => this . literalIdentifiers . get ( name ) ?? null
289+ }
290+ ) ;
291+ if ( callExprArguments === null ) {
292+ return ;
293+ }
294+
295+ const callExprArgumentNode = callExprArguments . at ( 0 ) ;
296+ if ( typeof callExprArgumentNode === "string" ) {
297+ this . literalIdentifiers . set (
298+ id . name ,
299+ Buffer . from ( callExprArgumentNode , "base64" ) . toString ( )
300+ ) ;
301+ }
302+ }
303+
279304 #walkImportDeclaration(
280305 node : ESTree . ImportDeclaration
281306 ) : void {
@@ -315,7 +340,7 @@ export class VariableTracer extends EventEmitter {
315340 id : ESTree . Identifier | ESTree . ObjectPattern
316341 ) : void {
317342 const moduleNameLiteral = node . arguments
318- . find ( ( argumentNode ) => isLiteralNode ( argumentNode )
343+ . find ( ( argumentNode ) => isLiteral ( argumentNode )
319344 && this . #traced. has ( stripNodePrefix ( argumentNode . value ) ) ) as ESTree . Literal | undefined ;
320345 if ( ! moduleNameLiteral ) {
321346 return ;
@@ -335,44 +360,17 @@ export class VariableTracer extends EventEmitter {
335360 }
336361 }
337362
338- #walkVariableDeclarationWithIdentifier(
339- variableDeclaratorNode : ESTree . VariableDeclarator
340- ) : void {
341- const { init } = variableDeclaratorNode ;
342- if ( init === null ) {
343- return void 0 ;
344- }
345-
346- switch ( init . type ) {
347- /**
348- * var root = freeGlobal || freeSelf || Function('return this')();
349- */
350- case "LogicalExpression" : {
351- for ( const { node } of extractLogicalExpression ( init ) ) {
352- this . #walkVariableDeclarationInitialization(
353- variableDeclaratorNode ,
354- node
355- ) ;
356- }
357-
358- return void 0 ;
359- }
360-
361- default :
362- return this . #walkVariableDeclarationInitialization(
363- variableDeclaratorNode
364- ) ;
365- }
366- }
367-
368- #walkVariableDeclarationInitialization(
363+ #walkVariableDeclaratorInitialization(
369364 variableDeclaratorNode : ESTree . VariableDeclarator ,
370- childNode = variableDeclaratorNode . init
365+ childNode : ESTree . Node | null = variableDeclaratorNode . init
371366 ) : void {
372367 if ( childNode === null ) {
373368 return ;
374369 }
375- const { id } = variableDeclaratorNode as any ;
370+ const { id } = variableDeclaratorNode ;
371+ if ( id . type !== "Identifier" ) {
372+ return ;
373+ }
376374
377375 switch ( childNode . type ) {
378376 // let foo = "10"; <-- "foo" is the key and "10" the value
@@ -381,33 +379,45 @@ export class VariableTracer extends EventEmitter {
381379 break ;
382380 }
383381
382+ /**
383+ * import os from "node:os";
384+ *
385+ * const foo = {
386+ * host: os.hostname(), <-- Property
387+ * ...{ bar: "hello world"} <-- SpreadElement
388+ * };
389+ * ^ ObjectExpression
390+ */
384391 case "ObjectExpression" : {
385- for ( const prop of childNode . properties ) {
386- switch ( prop . type ) {
387- case "Property" : {
388- this . #walkVariableDeclarationInitialization( variableDeclaratorNode ,
389- prop . value as ESTree . VariableDeclarator [ "init" ] ) ;
390- break ;
391- }
392- case "SpreadElement" : {
393- this . #walkVariableDeclarationInitialization( variableDeclaratorNode ,
394- prop . argument as ESTree . VariableDeclarator [ "init" ] ) ;
395- break ;
396- }
397- }
392+ for ( const property of childNode . properties ) {
393+ const node = match ( property )
394+ . with ( { type : "Property" } , ( prop ) => prop . value )
395+ . with ( { type : "SpreadElement" } , ( prop ) => prop . argument )
396+ . otherwise ( ( ) => null ) ;
397+
398+ node && this . #walkVariableDeclaratorInitialization(
399+ variableDeclaratorNode ,
400+ node
401+ ) ;
398402 }
399403 break ;
400404 }
401405
402406 case "ArrayExpression" : {
403407 for ( const element of childNode . elements ) {
404- this . #walkVariableDeclarationInitialization( variableDeclaratorNode , element ) ;
408+ this . #walkVariableDeclaratorInitialization(
409+ variableDeclaratorNode ,
410+ element
411+ ) ;
405412 }
406413 break ;
407414 }
408415
409416 case "SpreadElement" : {
410- this . #walkVariableDeclarationInitialization( variableDeclaratorNode , childNode . argument ) ;
417+ this . #walkVariableDeclaratorInitialization(
418+ variableDeclaratorNode ,
419+ childNode . argument
420+ ) ;
411421 break ;
412422 }
413423
@@ -448,23 +458,7 @@ export class VariableTracer extends EventEmitter {
448458 this . #walkRequireCallExpression( childNode , id ) ;
449459 }
450460 else if ( tracedFullIdentifierName === "atob" ) {
451- const callExprArguments = getCallExpressionArguments (
452- childNode ,
453- {
454- externalIdentifierLookup : ( name ) => this . literalIdentifiers . get ( name ) ?? null
455- }
456- ) ;
457- if ( callExprArguments === null ) {
458- break ;
459- }
460-
461- const callExprArgumentNode = callExprArguments . at ( 0 ) ;
462- if ( typeof callExprArgumentNode === "string" ) {
463- this . literalIdentifiers . set (
464- id . name ,
465- Buffer . from ( callExprArgumentNode , "base64" ) . toString ( )
466- ) ;
467- }
461+ this . #reverseAtob( childNode , id ) ;
468462 }
469463
470464 break ;
@@ -523,7 +517,7 @@ export class VariableTracer extends EventEmitter {
523517 }
524518
525519 if ( childNode . object . type === "CallExpression" ) {
526- this . #walkVariableDeclarationInitialization ( variableDeclaratorNode , childNode . object ) ;
520+ this . #walkVariableDeclaratorInitialization ( variableDeclaratorNode , childNode . object ) ;
527521 }
528522 break ;
529523 }
@@ -537,7 +531,7 @@ export class VariableTracer extends EventEmitter {
537531 if ( init === null ) {
538532 return ;
539533 }
540- const id = variableDeclaratorNode . id as any ;
534+ const { id } = variableDeclaratorNode as any ;
541535
542536 switch ( init . type ) {
543537 // const { process } = eval("this");
@@ -574,44 +568,53 @@ export class VariableTracer extends EventEmitter {
574568 }
575569 }
576570
577- walk ( node : ESTree . Node ) : void {
571+ #walkVariableDeclarator(
572+ node : ESTree . VariableDeclarator
573+ ) : void {
574+ // var foo; <-- no initialization here.
575+ if ( ! notNullOrUndefined ( node . init ) ) {
576+ return ;
577+ }
578+
579+ /**
580+ * const { foo } = {};
581+ * ^ ^ ObjectPattern (example)
582+ */
583+ if ( node . id . type !== "Identifier" ) {
584+ this . #walkVariableDeclarationWithAnythingElse( node ) ;
585+
586+ return ;
587+ }
588+
589+ // var root = freeGlobal || freeSelf || Function('return this')();
590+ if ( node . init . type === "LogicalExpression" ) {
591+ for ( const extractedNode of extractLogicalExpression ( node . init ) ) {
592+ this . #walkVariableDeclaratorInitialization(
593+ node ,
594+ extractedNode . node
595+ ) ;
596+ }
597+ }
598+ // const foo = "bar";
599+ else {
600+ this . #walkVariableDeclaratorInitialization( node ) ;
601+ }
602+ }
603+
604+ walk (
605+ node : ESTree . Node
606+ ) : void {
578607 switch ( node . type ) {
579608 case "ImportDeclaration" : {
580609 this . #walkImportDeclaration( node ) ;
581610 break ;
582611 }
583612 case "VariableDeclaration" : {
584- for ( const variableDeclaratorNode of node . declarations ) {
585- // var foo; <-- no initialization here.
586- if ( ! notNullOrUndefined ( variableDeclaratorNode . init ) ) {
587- continue ;
588- }
589-
590- if ( variableDeclaratorNode . id . type === "Identifier" ) {
591- this . #walkVariableDeclarationWithIdentifier( variableDeclaratorNode ) ;
592- }
593- else {
594- this . #walkVariableDeclarationWithAnythingElse( variableDeclaratorNode ) ;
595- }
596- }
613+ node . declarations . forEach (
614+ ( node ) => this . #walkVariableDeclarator( node )
615+ ) ;
597616 break ;
598617 }
599618 }
600619 }
601620}
602-
603- function stripNodePrefix ( value : any ) : any {
604- if ( typeof value !== "string" ) {
605- return value ;
606- }
607-
608- return value . startsWith ( kNodeModulePrefix ) ?
609- value . slice ( kNodeModulePrefix . length ) :
610- value ;
611- }
612-
613- function isLiteralNode (
614- node : ESTree . Node
615- ) : node is ESTree . Literal {
616- return node . type === "Literal" ;
617- }
0 commit comments