A vulnerability detection method of a JavaScript component
Patent Information
- Application Number
- CN202611137012.8
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2026-07-29
- Publication Date
- 2026-10-20
AI Technical Summary
1、通过识别原型链操作并生成原型链污点传播边,本发明能够准确追踪原型对象与实例对象之间的污点继承关系,解决了现有技术无法建模原型链上污点传递的问题,使得当原型对象被污染时,能够及时识别通过原型链继承导致的实例对象污染路径,从而有效检测基于原型链污染的攻击向量,显著降低了此类漏洞的漏报率。
Smart Images

Figure FT_1 
Figure SMS_1 
Figure SMS_2
Abstract
Description
Technical Field
[0001] This invention relates to the field of software security detection technology, and more specifically, to a method for detecting vulnerabilities in JavaScript components. Background Technology
[0002] With the rapid development of web application technologies, JavaScript has become a core language for front-end development and is widely used in server-side, mobile, and IoT devices. JavaScript components, as the basic units of code reuse, directly impact the reliability of the entire application system. However, the dynamic nature, weak typing, and rich syntax features of JavaScript (such as prototype chain inheritance, closures, and asynchronous callback mechanisms) make it difficult for traditional static analysis methods to accurately model its data flow and control flow behavior.
[0003] Existing static taint analysis techniques are primarily designed for statically typed languages such as Java and C / C++. When analyzing JavaScript code, they often overlook property inheritance relationships on the prototype chain, cross-scope references of closure variables, and the non-sequential execution characteristics of asynchronous callbacks. This leads to incomplete taint propagation path tracing and high false negative and false positive rates. Furthermore, existing methods lack targeted intermediate representation extensions for JavaScript-specific syntactic structures (such as destructuring assignment, spread operators, and arrow functions), further limiting analysis accuracy. Therefore, there is an urgent need for a vulnerability detection method that fully considers the characteristics of the JavaScript language and supports accurate modeling of data flow and control flow relationships to improve the accuracy and coverage of JavaScript component security analysis. Summary of the Invention
[0004] This invention provides a method for detecting vulnerabilities in JavaScript components, comprising: Obtain the source code of the target JavaScript component; parse the source code to obtain an intermediate representation; generate a basic data flow graph and a basic control flow graph based on the intermediate representation; perform JavaScript feature extraction operations on the intermediate representation, including: identifying prototype chain operations and generating prototype chain taint propagation edges, identifying closure structures and generating closure variable reference edges, and identifying asynchronous callback registrations and generating asynchronous control flow edges; add the prototype chain taint propagation edges and the closure variable reference edges to the basic data flow graph to obtain an extended data flow graph; add the asynchronous control flow edges to the basic control flow graph to obtain an extended control flow graph; perform static taint analysis on the extended data flow graph and the extended control flow graph according to a preset vulnerability detection rule set to obtain a taint propagation path set; and generate a vulnerability detection report based on the taint propagation path set.
[0005] Further, the step of parsing the source code to obtain an intermediate representation includes: performing lexical and syntactic analysis on the source code to generate an abstract syntax tree; performing semantic analysis on the abstract syntax tree to generate a symbol table, the symbol table containing variable type information and variable scope information; performing JavaScript-specific syntax node expansion processing on the abstract syntax tree, the JavaScript-specific syntax nodes including destructuring assignment nodes, spread operator nodes, and arrow function nodes, generating a many-to-one data mapping record from source property to target variable for the destructuring assignment node, generating a batch copy record from the spread object to the receiving array or object for the spread operator node, and generating a lexical scope binding record for the arrow function node; and using the abstract syntax tree, the symbol table, the data mapping record, the batch copy record, and the lexical scope binding record together as the intermediate representation.
[0006] Further, generating the basic data flow graph and the basic control flow graph based on the intermediate representation includes: generating the basic control flow graph using a basic block partitioning algorithm based on the abstract syntax tree and the symbol table. The basic block partitioning algorithm includes: traversing the abstract syntax tree, dividing the sequentially executed statement sequence into a basic block, and setting basic block boundaries at conditional branch statements, loop entry points, loop exit points, function call statements, and jump statements. The basic control flow graph includes multiple basic blocks and control flow edges between the multiple basic blocks. Based on the basic control flow graph, generating the basic data flow graph using a definition-reaching iteration algorithm includes: calculating a definition set and a reference set for each basic block, obtaining variable usage nodes reachable from each variable definition node by iteratively solving the data flow equation, and using the variable definition nodes, the variable usage nodes, and the data flow edges from the variable definition nodes to the variable usage nodes as the basic data flow graph.
[0007] Further, the step of identifying prototype chain operations and generating prototype chain taint propagation edges includes: traversing the abstract syntax tree and detecting prototype chain operation nodes; for each prototype chain operation node, determining the prototype object being assigned a value and the instance object receiving the assignment, and determining whether the prototype object has been marked as a tainted data source; when the prototype object has been marked as a tainted data source, adding an inheritance edge from the tainted data node of the prototype object to the tainted data node of the instance object in the basic data flow graph, the inheritance edge being used to indicate the taint propagation relationship on the prototype chain; when the prototype object has not been marked as a tainted data source, adding a potential propagation edge from the data node of the prototype object to the data node of the instance object in the basic data flow graph, and setting the activation condition of the potential propagation edge to the prototype object being subsequently marked as a tainted data source.
[0008] Further, the step of identifying closure structures and generating closure variable reference edges includes: traversing the abstract syntax tree, detecting function definition nodes, performing free variable analysis for each function definition node to obtain external variables referenced by the function definition node that are not defined in their own parameter list or local variables as a set of free variables; associating each external variable in the set of free variables with the location node inside the function definition node that uses the external variable; performing escape analysis on the function definition node to determine whether the function definition node is returned, stored in a global object, or passed as a parameter to an external function; if the result of the escape analysis is that the function definition node escapes, then adding a reference edge from the definition node of the external variable to the location node inside the function definition node, the reference edge being used to indicate the taint propagation relationship of the closure capture variable; if the result of the escape analysis is that the function definition node does not escape, then not adding the reference edge.
[0009] Further, the step of identifying asynchronous callback registrations and generating asynchronous control flow edges includes: traversing the abstract syntax tree and detecting asynchronous callback registration function call nodes; obtaining callback function nodes within the asynchronous callback registration function call nodes; determining the entry basic block of the callback function node; detecting whether there is a difference in event loop task queue type between the basic block where the asynchronous callback registration function call node is located and the entry basic block of the callback function node, wherein the event loop task queue type includes macro task queues and micro task queues; and adding asynchronous control flow edges carrying task type labels to the basic control flow graph based on the difference in event loop task queue types, wherein the asynchronous control flow edges point from the basic block where the asynchronous callback registration function call node is located to the entry basic block of the callback function node, and the task type label is used to indicate whether the callback function is executed in the macro task queue or the micro task queue.
[0010] Furthermore, the preset vulnerability detection rule set includes multiple vulnerability patterns; each vulnerability pattern is associated with a taint source feature set and a taint convergence point feature set; the step of performing static taint analysis on the extended data flow graph and the extended control flow graph according to the preset vulnerability detection rule set to obtain a taint propagation path set further includes: selecting the current vulnerability pattern from the preset vulnerability detection rule set; identifying nodes in the extended data flow graph that conform to the taint source feature set as taint source nodes according to the current vulnerability pattern; and identifying nodes in the extended data flow graph that conform to the taint convergence point feature set as taint convergence point nodes according to the current vulnerability pattern.
[0011] Furthermore, the step of performing static taint analysis on the extended data flow graph and the extended control flow graph according to a preset vulnerability detection rule set to obtain a taint propagation path set also includes: tracing data flow paths from the taint source node to the taint convergence node according to the extended data flow graph, and recording the data flow paths as candidate taint propagation paths; verifying the control flow feasibility in the candidate taint propagation paths according to the extended control flow graph, and determining the verified candidate taint propagation paths as valid taint propagation paths; and aggregating the valid taint propagation paths to obtain the taint propagation path set.
[0012] Further, generating a vulnerability detection report based on the taint propagation path set includes: for each valid taint propagation path in the taint propagation path set, obtaining the vulnerability pattern identifier corresponding to the path, the source code location information of the taint source node, the source code location information of the taint convergence node, and the sequence of intermediate nodes traversed by the path; generating a structured vulnerability report based on the vulnerability pattern identifier, the source code location information, and the sequence of intermediate nodes, wherein the structured vulnerability report includes a vulnerability type field, a vulnerability triggering path field, and a vulnerability location field.
[0013] Furthermore, after generating the abstract syntax tree, the method further includes: performing cross-function call analysis on the abstract syntax tree; associating the actual parameter nodes at the calling function with the formal parameter nodes of the called function according to the function call relationship graph; and adding cross-function definition-use chains in the extended data flow graph. The cross-function call analysis includes: constructing a global function call graph, where the nodes are function definition nodes and the edges are call relationships; identifying higher-order function call patterns; when the actual parameter itself is a function node, adding a higher-order pass edge from the return value node of the actual parameter function to the formal parameter node of the called function in the extended data flow graph; and identifying callback function parameter passing patterns; when the actual parameter is a callback function node, adding a reverse taint propagation edge from the parameter node inside the callback function node to the actual parameter node at the call point inside the called function in the extended data flow graph.
[0014] The embodiments of the present invention have at least the following beneficial effects: 1. By identifying prototype chain operations and generating prototype chain taint propagation edges, this invention can accurately track the taint inheritance relationship between prototype objects and instance objects, solving the problem that existing technologies cannot model taint propagation on prototype chains. This enables timely identification of instance object taint paths caused by prototype chain inheritance when a prototype object is tainted, thereby effectively detecting attack vectors based on prototype chain taints and significantly reducing the false negative rate of such vulnerabilities.
[0015] 2. By identifying closure structures and generating closure variable reference edges, this invention can accurately model the capture relationship between function definition nodes and external variables. Combined with escape analysis, it can determine whether the closure has escaped its scope, solving the problem that existing technologies have difficulty tracking cross-scope variable references. This allows the use of external tainted variables within the closure to be fully included in the taint propagation path, improving the completeness of cross-function data flow analysis and thus enhancing the detection capability of closure-related vulnerabilities.
[0016] 3. By identifying asynchronous callback registrations and generating asynchronous control flow edges carrying task type tags, this invention can distinguish the execution differences between macro task queues and micro task queues, establish control flow associations between asynchronous callback registration points and callback function entry points, solve the problem of lacking asynchronous execution context modeling in existing technologies, and enable accurate verification of the control flow feasibility of taint propagation paths in non-sequential execution callback functions, thereby effectively detecting security vulnerabilities in asynchronous scenarios and improving the applicability and accuracy of static taint analysis in asynchronous programming modes. Attached Figure Description
[0017] The above and other objects, features, and advantages of exemplary embodiments of the present invention will become readily apparent from the following detailed description taken in conjunction with the accompanying drawings. Several embodiments of the invention are illustrated in the drawings by way of example and not limitation, wherein: Figure 1 This is a flowchart illustrating a vulnerability detection method for JavaScript components provided in an embodiment of the present invention. Detailed Implementation
[0018] The principles and spirit of the invention will now be described with reference to several exemplary embodiments. It should be understood that these embodiments are provided merely to enable those skilled in the art to better understand and implement the invention, and are not intended to limit the scope of the invention in any way. Rather, these embodiments are provided to make the invention more thorough and complete, and to fully convey the scope of the invention to those skilled in the art.
[0019] Those skilled in the art will recognize that embodiments of the present invention can be implemented as a system, apparatus, device, method, or computer program product. Therefore, the present invention can be specifically implemented in the following forms: entirely hardware, entirely software (including firmware, resident software, microcode, etc.), or a combination of hardware and software.
[0020] It should be noted that the number of any elements in the accompanying drawings is for illustrative purposes only and not as a limitation, and any naming is for distinction only and has no limiting meaning.
[0021] The following is for reference. Figure 1 , Figure 1 This is a flowchart illustrating a vulnerability detection method for JavaScript components according to an embodiment of the present invention. Figure 1 As shown, a vulnerability detection method for JavaScript components includes: S1: Obtain the source code of the target JavaScript component. The method retrieves the source code text of the JavaScript component to be tested. The target JavaScript component refers to an executable software unit written in JavaScript, which can be a standalone .js file, a Node.js module containing multiple files, an inline script in a front-end web application, or an external script resource. The vulnerability detection method in this application aims to discover potential security vulnerabilities in this component, such as cross-site scripting attacks, prototype pollution, command injection, and path traversal. During implementation, the source code is read through a file system interface or a network request interface. For example, for local files, the `fs.readFileSync` function provided by the Node.js environment is used, specifying the file path and encoding type such as UTF-8, to synchronously read the file content string. For remote script resources, an HTTP client library such as axios or the built-in `fetch` function is used to send a GET request to the target URL and receive the text content in the response body. After successful reading, the source code string is temporarily stored in a memory variable for subsequent parsing.
[0022] S2: Parse the source code to obtain an intermediate representation; The source code string obtained from S1 is converted into a structured intermediate representation. The intermediate representation is a combination of an abstract syntax tree, a symbol table, and various JavaScript-specific syntax records, used to preserve the syntactic structure and semantic information of the source code, facilitating the subsequent construction of a graph model.
[0023] S21: Perform lexical analysis and syntax analysis on the source code to generate an abstract syntax tree; A JavaScript parser is used to perform lexical and syntactic analysis on the source code string. This application can use either Esprima 4.0 or Acorn 8.0, both of which fully support the ECMAScript 2022 standard. Lexical analysis decomposes the source code character sequence into a token stream. Token types include keywords such as `function`, identifiers such as variable names, operators such as the plus sign, literals such as numbers, and strings. Syntactic analysis organizes the token stream into a tree structure, or Abstract Syntax Tree (AST), according to ECMAScript grammar rules. Each node in the AST corresponds to a grammatical structure. The root node is of type `Program`, and its `body` property contains an array of statement nodes. Taking the input code `var a = 1;` as an example, a generated `VariableDeclaration` node contains a `VariableDeclarator` child node. The `id` field of this child node points to the `Identifier` node with a value of `a`, and the `init` field points to the `Literal` node with a value of 1. The AST is stored in memory in JSON format for subsequent traversal.
[0024] S22: Perform semantic analysis on the abstract syntax tree to generate a symbol table, which contains variable type information and variable scope information; The abstract syntax tree is traversed to construct a symbol table for each scope. The symbol table is a key-value mapping structure, where the key is the variable or function name, and the value is a record describing the symbol's properties. Semantic analysis includes: identifying the location of each variable declaration, determining its scope boundaries, and handling JavaScript's unique variable hoisting mechanism. Variables declared with `var` are hoisted to the top of the function scope, while `let` and `const` have block scope and a temporal dead zone. Variable type information is obtained in static analysis through type inference on the right-hand side of the assignment expression. For example, `var x = "hello"` infers that `x` is a string, and `var y=[1,2,3]` infers that `y` is an array. Cases where the specific type cannot be determined are marked as unknown. The symbol table is implemented as a nested hash table, with the outer table corresponding to the global scope and the inner table corresponding to the function scope or block scope. Each symbol record contains a type identifier such as string, number, boolean, object, or function, a reference to the scope boundary node, and the line number of the source code where the definition is located.
[0025] S23: Perform JavaScript-specific syntax node expansion processing on the abstract syntax tree. These JavaScript-specific syntax nodes include destructuring assignment nodes, spread operator nodes, and arrow function nodes. For the destructuring assignment nodes, generate a many-to-one data mapping record from the source property to the target variable. For the spread operator nodes, generate a batch copy record from the spread object to the receiving array or object. For the arrow function nodes, generate a lexical scope binding record. The abstract syntax tree (AST) is traversed to identify and process JavaScript's unique syntactic structures compared to traditional languages. For destructuring assignment nodes, the pattern can be object destructuring such as `{a, b} = obj` or array destructuring such as `[x, y] = arr`. For each target variable in the destructuring pattern, the corresponding property or index position in the source object or source array is found, generating a data mapping record from the source property path to the target variable node. If nested destructuring exists such as `{c: {d}} = obj`, it is recursively expanded.
[0026] For expansion operator nodes, `[...arr]` appears in array literals, or `{...obj}` appears in object literals. A batch copy record is generated, recording the expanded expression node and the array or object node that receives the expansion result. For arrow function nodes such as `(x) =>x+1`, they do not have independent `this` bindings; instead, they capture the `this` value at the time of definition. A lexical scope binding record is generated, recording the arrow function node and the `this` and `arguments` variables of its inherited lexical environment (i.e., the parent scope). These records are stored in an independent data structure and associated with the corresponding node in the abstract syntax tree via node ID.
[0027] S24: The abstract syntax tree, the symbol table, the data mapping record, the batch copy record, and the lexical scope binding record are used together as the intermediate representation; The abstract syntax tree object, symbol table object, and three types of record lists are packaged into a single comprehensive data structure called the intermediate representation. In memory implementation, this can be encapsulated using JavaScript object literals, such as `{ ast, symbolTable, destructuringMaps, spreadRecords, arrowBindings}`. This intermediate representation provides a complete syntactic and semantic view of the source code, allowing subsequent steps to extract necessary information directly from it without re-parseing the source code.
[0028] S25: Perform cross-function call analysis on the abstract syntax tree, and associate the actual parameter nodes at the calling function with the formal parameter nodes of the called function according to the function call relationship graph, and record the cross-function definition-usage chain; This step is executed immediately after generating the abstract syntax tree (AST), but the recorded cross-function relationships will be added as edges to the graph later when the extended data flow graph is generated. Specifically, the implementation is as follows: First, a global function call graph is constructed, traversing all function definition nodes and function call expressions in the AST. For each call point, based on the name or function expression of the called function, the actual function definition node it points to is resolved using the symbol table. The nodes in the function call graph are each function definition node, and edges point from the caller node to the callee node. Then, for each call point, its actual parameter nodes are associated with the corresponding formal parameter nodes of the called function, generating a cross-function definition record using a chain, in the format `{ callerFunc, callSite, argIndex, paramNode}`. This record is stored in a temporary list, and will be converted into actual data flow edges when S5 generates the extended data flow graph.
[0029] S26: Identify higher-order function call patterns. When the actual argument itself is a function node, record the higher-order pass-through edge from the return value node of the actual argument function to the formal parameter node of the called function. During cross-function call analysis, higher-order function call patterns are detected. Each call point is traversed, and the type of the actual argument is checked. If the actual argument is a function expression or a function name node, the call point is marked as a higher-order function call. For example, in `Array.prototype.map(arr, function(x){ return x2;})`, the second actual argument is an anonymous function. In this case, the return value node of the `return` statement inside the function is extracted. If the function body has multiple `return` statements or no `return` statements, the return value is marked as unknown. A higher-order transitive edge record is generated, containing a mapping from the return value node to the corresponding parameter node of the called function. This record is temporarily stored and will be added as an edge when generating the extended data flow graph.
[0030] S27: Identify the parameter passing pattern of the callback function. When the actual parameter is a callback function node, record the reverse taint propagation edge from the parameter node inside the callback function node to the actual parameter node at the call point inside the called function. Continue identifying callback function parameter passing patterns. When a callback function node is detected as an actual argument at the call point, such as `callback` in `setTimeout(callback, 1000)`, analyze the parameter list of that callback function. Then, locate the position where the callback function is called within the called function. For built-in functions like `setTimeout`, their internal implementation is not visible, but this application uses a pre-built model knowledge base to know that `setTimeout` will call the callback function in a future event loop, passing an actual argument that is usually `undefined` or a timer ID. For user-defined higher-order functions, their function bodies need to be analyzed to find the expression that calls the callback function node and extract the actual argument node passed during the call. Generate a reverse taint propagation edge record, with the direction pointing from the parameter node inside the callback function to the actual argument node at the call point inside the called function. This edge allows taints to flow from the external environment into the callback function, used to detect vulnerabilities in the callback.
[0031] S3: Generate a basic data flow graph and a basic control flow graph based on the intermediate representation; Based on the obtained intermediate representations, the basic control flow graph and basic data flow graph of the program are constructed respectively. The basic control flow graph describes the possible order of statement execution, and the basic data flow graph describes the propagation path of variable values between nodes. Both are directed graphs, with nodes representing statements or basic blocks and edges representing flow relationships.
[0032] S31: Based on the abstract syntax tree and the symbol table, the basic control flow graph is generated using a basic block partitioning algorithm. The basic block partitioning algorithm includes: traversing the abstract syntax tree, dividing the sequentially executed statement sequence into a basic block, and setting basic block boundaries at conditional branch statements, loop entry points, loop exit points, function call statements, and jump statements. The basic control flow graph includes multiple basic blocks and control flow edges between the multiple basic blocks.
[0033] The abstract syntax tree (AST) divides the sequence of statements into basic blocks. A basic block is a maximally continuous sequence of statements, whose execution always begins with the first statement and ends with the last statement, without any branching or jumping in between. The partitioning algorithm is as follows: Iterate through the list of statements in the AST sequentially, initializing the current basic block to empty. For each statement, if the current basic block is empty, add the statement to the block; if the current basic block is not empty and the statement is a conditional branch statement such as if, switch, ternary operator, or the entry point of a loop statement such as for, while, or do-while, or the exit point of a loop statement such as break or continue, or a function call statement that may throw an exception such as JSON.parse, or a jump statement such as return or throw, then close the current basic block, make the statement the first statement of the new basic block, and then close the new block if the statement is a jump statement.
[0034] For conditional branch statements, a new basic block boundary is set at the beginning of the statement sequence for each branch, and the branch condition expression is treated as a separate preceding basic block. Boundaries are set at the entry point of loop statements, the statement sequence within the loop body is a separate block, and a successor block is set at the loop exit. After partitioning, a list of basic blocks is obtained, and then control flow edges are added according to the jump relationships between statements: unconditional edges are added between two sequentially executed blocks; edges marked as true or false are added for conditional branches based on true or false conditions; loops add back edges from the loop body block to the loop condition block and edges from the loop exit to the successor block. The resulting basic control flow graph nodes are basic blocks, and the edges represent the control flow direction. For example, an if-else structure will produce a conditional expression block, a then block, an else block, and a merge block.
[0035] S32: Based on the basic control flow graph, the basic data flow graph is generated using the reach-definition iterative algorithm. The reach-definition iterative algorithm includes: calculating the definition set and reference set for each basic block, obtaining the variable usage node that each variable definition node can reach by iteratively solving the data flow equation, and using the variable definition node, the variable usage node, and the data flow edge from the variable definition node to the variable usage node as the basic data flow graph. First, for each basic block B, compute its definition set GEN(B) and reference set REF(B). The definition set contains the nodes in B where variables are assigned values, such as the definition node of x in `x = 5`. The reference set contains the nodes in B where variable values are used, such as the usage node of x in `y = x + 1`. Then, an iterative algorithm to reach definitions is used to solve for which usage nodes are reachable from each definition node. The data flow equation is as follows: Here, B represents a basic block, pred(B) represents the set of predecessor basic blocks of B, IN(B) represents the set of definitions entering B (i.e., which definitions were valid before B), OUT(B) represents the set of definitions leaving B, GEN(B) represents the set of definitions generated in B, and KILL(B) represents the set of overridden definitions in B. Each definition is a triple (variable name, definition node, block). The calculation rule for KILL(B) is: if there is a new definition of variable v in B, then all other definitions of v in all other blocks will be killed. The iteration starts with all blocks' IN and OUT initially being empty sets, and is repeated until all sets no longer change.
[0036] After convergence, for each usage node u (the use of variable v), collect all definition nodes d that can reach u, and add a directed edge from d to u in the basic data flow graph, called a data flow edge. Furthermore, the variable definition node and the usage node themselves are also treated as nodes in the graph. In a typical data flow graph, the number of nodes is approximately 1.5 times the number of nodes in the abstract syntax tree, and the number of edges is approximately 2 to 3 times the number of nodes. The time complexity of this algorithm is O(...). ), where N is the number of basic blocks. In actual projects, N is usually less than 100, which can ensure efficient operation.
[0037] S4: Perform JavaScript feature extraction operations on the intermediate representation. The JavaScript feature extraction operations include: identifying prototype chain operations and generating prototype chain taint propagation edges, identifying closure structures and generating closure variable reference edges, and identifying asynchronous callback registrations and generating asynchronous control flow edges. To leverage JavaScript's unique language features, additional propagation and flow edges are extracted from the intermediate representation. These features include prototype chains, closures, and asynchronous callbacks, which are the main reasons why traditional static analysis tools fail to detect vulnerabilities.
[0038] S41: Traverse the abstract syntax tree and detect the following three types of nodes as prototype chain operation nodes: nodes assigned using the double underscore `proto` keyword, nodes that call the `Object.setPrototypeOf` function, and nodes that create objects using the `Object.create` method. The abstract syntax tree generated by S21 is traversed, using node type matching and property name matching to locate prototype chain-related operations. The first type is member expression nodes whose property field value is the string __proto__, and whose parent node is an assignment expression. For example, the code `obj.__proto__ = parent`. The second type is call expression nodes, where `callee` is a member expression, `object` is an Identifier node named "Object", and `property` is an Identifier node named "setPrototypeOf". The third type is call expression nodes, where `callee` is a member expression, `object` is an Identifier node named "Object", and `property` is an Identifier node named "create". Each detected node is added to the prototype chain operation node list.
[0039] S42: For each of the prototype chain operation nodes, determine the prototype object to be assigned and the instance object to receive the assignment; For each prototype chain operation node, extract the prototype object and instance object based on its type. For the `__proto__` assignment node, `obj` in `obj.__proto__` on the left is the instance object, and the expression on the right is the prototype object. For the `Object.setPrototypeOf(obj, proto)` call, the first parameter `obj` is the instance object, and the second parameter `proto` is the prototype object. For the `Object.create(proto)` call, the parameter `proto` is the prototype object, and the return value is a newly created instance object. This return value node is typically the target of variable declaration or assignment in the abstract syntax tree. The extracted nodes may be identifiers, member expressions, or literals, and their positions in the abstract syntax tree need to be recorded.
[0040] S43: Determine whether the prototype object has been marked as a tainted data source; Maintain a global set of tainted data source tags, initially empty. During vulnerability detection rule execution, nodes are added to this set based on preset tainted source characteristics. This step checks whether the prototype object node extracted by S42 already exists in this set. Tainted data sources typically include user input functions such as `document.getElementById().value`, URL parameters such as `location.search`, and local storage data such as `localStorage.getItem`.
[0041] S44: When the prototype object has been marked as a tainted data source, add an inheritance edge from the tainted data node of the prototype object to the tainted data node of the instance object in the basic data flow graph. The inheritance edge is used to indicate the tainted propagation relationship on the prototype chain. If the prototype object is a tainted data source, add a directed edge to the underlying data flow graph, pointing from the tainted data node of the prototype object to the tainted data node of the instance object. This edge is named the inheritance edge. The semantics are: if a taint exists on the prototype object, it will be inherited by the instance object when accessing the prototype property, traced through the prototype chain. For example, if `parent` is tainted, then after `obj.__proto__ = parent`, `obj.anyAttr` will actually return `parent.anyAttr`, and the taint is propagated.
[0042] S45: When the prototype object is not marked as a tainted data source, add a potential propagation edge from the data node of the prototype object to the data node of the instance object in the basic data flow graph, and set the activation condition of the potential propagation edge to the prototype object being subsequently marked as a tainted data source. If the prototype object is not currently a tainted data source, a potential propagation edge is added, and a conditional predicate of the form `isTainted(protoNode) == true` is attached to this edge. In subsequent taint propagation analysis, when a prototype object node is marked as tainted, this potential propagation edge automatically becomes a valid edge, triggering taint propagation. This mechanism avoids re-traversing the prototype object, improving analysis efficiency.
[0043] S51: Traverse the abstract syntax tree, detect function definition nodes, perform free variable analysis for each function definition node, and obtain the external variables referenced by the function definition node that are not defined in its own parameter list or local variables as the set of free variables. Traverse the abstract syntax tree (AST) to find all `FunctionDeclaration`, `FunctionExpression`, and `ArrowFunctionExpression` nodes. For each function node, perform free variable analysis: recursively traverse the AST of the function body, collect all occurrences of the `Identifier` node, exclude identifiers in the parameter list, exclude local variables declared using `var`, `let`, and `const` within the function body, and exclude identifiers from recursive calls to the function name itself. The remaining identifiers are the free variables, which are then grouped into a free variable set. For example, in `function outer(){ let a=1; function inner(){ console.log(a);}}`, the free variable set of the `inner` function contains `a`.
[0044] S52: Associate each external variable in the set of free variables with the location node inside the function definition node that uses the external variable; For each variable in the set of free variables, locate all nodes in the function body's AST that use this variable, such as variable access expressions and function call arguments. Create a map where the keys are the definition nodes of the external variable (declaration nodes in the outer scope), and the values are a list of all nodes that use the variable within the function. This map is stored in a closure relation table.
[0045] S53: Perform escape analysis on the function definition node to determine whether the function definition node is returned, stored in the global object, or passed as a parameter to an external function. Escape analysis is used to determine whether a function's lifetime will exceed its defined scope. Specifically, it checks: 1) whether the function node appears in the expression of a return statement; 2) whether the function node is assigned to a property of a global object, such as `window.myFunc = function(){}`; 3) whether the function node is passed as an argument to a function that might save it externally, such as setTimeout, addEventListener, Promise.then, or any user-defined higher-order function. This application implements an escape analysis module that tracks function node references through data flow analysis. If any of the above conditions exist, it is marked as escaped; otherwise, it is marked as not escaped.
[0046] S54: If the escape analysis results in the function definition node escaping, then add a reference edge from the definition node of the external variable to the internal usage node in the basic data flow graph. The reference edge is used to indicate the taint transitivity of the closure capture variable. For an escaping function, the captured external variables may still be alive when the function is called lazily, thus taints can propagate from external variables into the function's interior. Traversing the mapping established by S52, defining a node for each external variable and a node for each internal use location, a directed edge called a closure reference edge is added to the underlying data flow graph.
[0047] S55: If the result of the escape analysis is that the function definition node has not escaped, then the reference edge is not added; Functions that do not escape can only be called synchronously within their defined scope. The lifetime of their external variables has already been covered by the normal data flow. Adding closure references would result in redundant paths, so they are skipped.
[0048] S61: Traverse the abstract syntax tree and detect asynchronous callback registration function call nodes, including setTimeout nodes, setInterval nodes, addEventListener nodes, Promise.then nodes, and async function call nodes. Traverse the abstract syntax tree to identify the invocation point for asynchronous callback registration. Matching conditions: the call expression's callee name is setTimeout, setInterval, or addEventListener; or the callee is a member expression with the property name then and the object type is Promise; or the function call node itself is a call to an async function because the async function returns a Promise, implicitly generating a callback after its invocation. For each matching node, record it as an asynchronous callback registration node.
[0049] S62: Obtain the callback function node in the asynchronous callback registration function call node; Extract callback function nodes according to API conventions. This includes the first parameter node of `setTimeout` and `setInterval`; the second parameter node of `addEventListener`; and the first parameter node of `Promise.then`. While async function calls themselves don't directly provide callbacks, their `then` method is reflected in the call result, so subsequent `then` calls require further analysis. If the callback function node is an `Identifier` or `FunctionExpression`, use it directly; otherwise, ignore it.
[0050] S63: Determine the entry basic block of the callback function node; Locate the first basic block corresponding to the callback function body in the basic control flow graph. For a FunctionExpression node, its function body is a BlockStatement, and the basic block containing the first executable statement in this block is the entry basic block. If the callback function is empty, a virtual empty basic block is created as the entry point.
[0051] S64: Detect whether there is a difference in event loop task queue type between the basic block where the asynchronous callback registration function call node is located and the entry basic block of the callback function node. The event loop task queue type includes macro task queue and micro task queue. The JavaScript event loop divides asynchronous tasks into macro tasks and micro tasks. Callbacks for `setTimeout`, `setInterval`, and I / O operations are macro tasks; callbacks for `Promise.then`, `process.nextTick`, and `MutationObserver` are micro tasks. Micro tasks execute after the current macro task has finished executing and before the next macro task begins. This step determines the task type based on the API type of the registered node and records the differences. For example, callbacks registered with `setTimeout` execute in the macro task queue, while callbacks registered with `Promise.then` execute in the micro task queue.
[0052] S65: Based on the difference in the event loop task queue type, add an asynchronous control flow edge carrying a task type label to the basic control flow graph. The asynchronous control flow edge points from the basic block where the asynchronous callback registration function call node is located to the entry basic block of the callback function node. The task type label is used to indicate whether the callback function is executed in the macro task queue or the micro task queue. Add a directed edge to the basic control flow graph, running from the basic block containing the registration node to the basic block where the callback entry point is located, and label it macro or micro. This edge indicates that the control flow asynchronously branches off at the registration point and is transferred to the callback function for execution in a future event loop cycle. This edge, together with the synchronous control flow edge, forms the extended control flow graph.
[0053] S5: Based on the basic data flow graph, add the prototype chain taint propagation edge and the closure variable reference edge to obtain the extended data flow graph. The inheritance edges and potential propagation edges generated in S44 and S45, as well as the closure reference edges generated in S54, are all incorporated into the basic data flow graph obtained in S32. Simultaneously, the cross-function definition-use chains, higher-order transitive edges, and reverse taint propagation edges recorded in S25, S26, and S27 are also added as directed edges to the graph. The expanded graph is called the extended data flow graph, which additionally covers complex data flow scenarios such as JavaScript prototype chain pollution, closure capture, and cross-function higher-order calls.
[0054] S6: Add the asynchronous control flow edge based on the basic control flow graph to obtain the extended control flow graph; The expanded graph, called the extended control flow graph, includes not only synchronous control flows such as sequence, branch, and loop, but also asynchronous control flow edges pointing to the entry point of asynchronous callback execution. This graph is used for subsequent verification of whether taint propagation paths are feasible in the actual execution sequence.
[0055] S7: Based on the preset vulnerability detection rule set, perform static taint analysis on the extended data flow graph and the extended control flow graph to obtain a taint propagation path set; Static taint analysis is performed on the extended data flow graph and extended control flow graph using a pre-defined set of vulnerability detection rules. Static taint analysis is a technique that discovers security violations in information flow by tracking data markers without running a program. The pre-defined set of vulnerability detection rules is stored in a JSON file, and each rule contains a rule ID, vulnerability type, taint source characteristics, taint convergence point characteristics, and an optional processing function. Specifically: S71: Select the current vulnerability mode from the preset vulnerability detection rule set. Read the rule set file and select a rule as the current analysis target, either sequentially or by priority. For example, select the rule with rule ID XSS-001, whose taint source characteristics are `location.search`, `document.cookie`, etc., and taint convergence point characteristics are `innerHTML` assignment, `document.write` call, etc.
[0056] S72: Based on the current vulnerability pattern, identify nodes that match the taint source feature set from the extended data flow graph as taint source nodes; Traverse all nodes in the extended data flow graph, performing pattern matching between the node's source code features and the taint source feature set in the current rule. Matching methods support exact string matching, regular expression matching, and AST structure matching. For example, if the node's code is `window.location.search`, and the feature set contains `location.search`, then the match is successful. All matching nodes are marked as taint source nodes, and their positions are recorded.
[0057] S73: Based on the current vulnerability pattern, identify nodes that conform to the taint convergence point feature set from the extended data flow graph as taint convergence point nodes; Similarly, iterate through the nodes and match the taint convergence point feature set for the current rule. For example, if the node is `element.innerHTML=userInput` and the feature contains the assignment operation `innerHTML`, then the match is successful and it is marked as a taint convergence point node.
[0058] S74: Based on the extended data flow graph, trace the data flow path that can reach the taint convergence point node from the taint source node, and record the data flow path as a candidate taint propagation path; Starting from each taint source node, perform a depth-first search or breadth-first search on the expanded data flow graph to find a path that can reach any taint convergence node. A maximum path length threshold is set to 200 steps by default; the search stops if this threshold is exceeded to avoid explosion. Each found path is recorded as a sequence of nodes and edge types, stored as a candidate taint propagation path. If a potential propagation edge is encountered during the search, check if its activation condition is met. If it is, it is considered a valid edge and the traversal continues; otherwise, the branch is skipped.
[0059] S75: Based on the extended control flow graph, verify the control flow feasibility of the candidate taint propagation path, and determine the verified candidate taint propagation path as the effective taint propagation path. For each candidate path, extract the basic block or statement positions corresponding to all nodes in the path. Then, check the extended control flow graph for control flow edges between adjacent nodes. Since the extended control flow graph contains synchronous and asynchronous edges, connections across asynchronous edges must be allowed during verification. Specifically, if two adjacent nodes belong to different basic blocks, check if there is a directed edge in the extended control flow graph from the basic block of the first node to the basic block of the second node. If all adjacent nodes in the path satisfy this condition, the path passes verification and becomes a valid taint propagation path. Otherwise, the path is excluded.
[0060] S76: Collect the effective taint propagation paths to obtain the taint propagation path set; All valid taint propagation paths that have been verified are stored in an array or set called the taint propagation path set. Each path contains complete information about the source, intermediate steps, and the destination.
[0061] S8: Generate a vulnerability detection report based on the taint propagation path set; This step converts the taint propagation path set obtained from S76 into a vulnerability report that is either human-readable or machine-readable.
[0062] S81: For each valid taint propagation path in the taint propagation path set, obtain the vulnerability pattern identifier corresponding to the path, the source code location information of the taint source node, the source code location information of the taint convergence node, and the sequence of intermediate nodes traversed by the path. Traverse the set of taint propagation paths and extract the following fields for each path: the rule ID that triggered the path, such as XSS-001; the file name, line number, column number, and source code fragment of the taint source node; similar location information of the taint convergence point node; and the sequence of all intermediate nodes on the path, with each node containing node type, variable name, operation type, etc.
[0063] S82: Generate a structured vulnerability report based on the vulnerability pattern identifier, the source code location information, and the intermediate node sequence. The structured vulnerability report includes a vulnerability type field, a vulnerability trigger path field, and a vulnerability location field. Organize the information extracted from S81 into a JSON object format. For example: json { "vuln_type": "Cross-Site Scripting", "rule_id": "XSS-001", "source": {"file": "app.js", "line": 12, "column": 5, "code": "varquery = location.search"}, "sink": {"file": "app.js", "line": 45, "column": 10, "code": "div.innerHTML = query"}, "propagation_path": [ {"step":1, "node": "location.search", "operation": "read"}, {"step":2, "node": "query", "operation": "assign"}, {"step":3, "node": "innerHTML", "operation": "write"} ] } The report can be output to the console, written to a file, or sent to the security management system via API, allowing developers to locate and fix vulnerabilities.
[0064] Furthermore, the storage medium in the embodiments of this application stores program instructions capable of implementing all the above methods. These program instructions can be stored in the storage medium in the form of a software product, including several instructions to cause a computer device (which may be a personal computer, server, or network device, etc.) or processor to execute all or part of the steps of the methods described in the various embodiments of this application. The aforementioned storage medium includes various media capable of storing program code, such as USB flash drives, portable hard drives, read-only memory (ROM), random access memory (RAM), magnetic disks, or optical disks, or terminal devices such as computers, servers, mobile phones, and tablets.
[0065] The above description is merely an explanation of some preferred embodiments of the present invention and the technical principles employed. Those skilled in the art should understand that the scope of the invention as described in the embodiments of the present invention is not limited to technical solutions formed by specific combinations of the above-described technical features, but should also cover other technical solutions formed by arbitrary combinations of the above-described technical features or their equivalents without departing from the above-described inventive concept. For example, technical solutions formed by substituting the above-described features with (but not limited to) technical features with similar functions disclosed in the embodiments of the present invention.
Claims
1. A method for vulnerability detection in JavaScript components, characterized in that, include: Obtain the source code of the target JavaScript component; The source code is parsed to obtain an intermediate representation; Based on the intermediate representation, generate a basic data flow graph and a basic control flow graph; Perform a JavaScript feature extraction operation on the intermediate representation, the JavaScript feature extraction operation including: Identify prototype chain operations and generate prototype chain taint propagation edges; identify closure structures and generate closure variable reference edges; identify asynchronous callback registrations and generate asynchronous control flow edges. Based on the basic data flow graph, the prototype chain taint propagation edge and the closure variable reference edge are added to obtain the extended data flow graph; Based on the basic control flow graph, the asynchronous control flow edge is added to obtain the extended control flow graph; Based on the preset vulnerability detection rule set, static taint analysis is performed on the extended data flow graph and the extended control flow graph to obtain a taint propagation path set; A vulnerability detection report is generated based on the set of taint propagation paths.
2. The method according to claim 1, characterized in that, The process of parsing the source code to obtain an intermediate representation includes: Lexical and syntactic analysis are performed on the source code to generate an abstract syntax tree; Semantic analysis is performed on the abstract syntax tree to generate a symbol table, which contains variable type information and variable scope information. JavaScript-specific syntax node expansion processing is performed on the abstract syntax tree. The JavaScript-specific syntax nodes include destructuring assignment nodes, spread operator nodes, and arrow function nodes. For the destructuring assignment nodes, a many-to-one data mapping record from the source property to the target variable is generated. For the spread operator nodes, a batch copy record from the spread object to the receiving array or object is generated. For the arrow function nodes, a lexical scope binding record is generated. The abstract syntax tree, the symbol table, the data mapping record, the batch copy record, and the lexical scope binding record are collectively used as the intermediate representation.
3. The method according to claim 2, characterized in that, The step of generating a basic data flow graph and a basic control flow graph based on the intermediate representation includes: generating the basic control flow graph using a basic block partitioning algorithm based on the abstract syntax tree and the symbol table, wherein the basic block partitioning algorithm includes: Traverse the abstract syntax tree and divide the sequentially executed statement sequence into a basic block. Set basic block boundaries at conditional branch statements, loop entry points, loop exit points, function call statements, and jump statements. The basic control flow graph includes multiple basic blocks and control flow edges between the multiple basic blocks. Based on the aforementioned basic control flow graph, the underlying data flow graph is generated using an arrival-definition iterative algorithm, which includes: For each basic block, a definition set and a reference set are calculated. By iteratively solving the data flow equation, the variable usage nodes that each variable definition node can reach are obtained. The variable definition nodes, the variable usage nodes, and the data flow edges from the variable definition nodes to the variable usage nodes are used as the basic data flow graph.
4. The method according to claim 2, characterized in that, The process of identifying prototype chain operations and generating prototype chain taint propagation edges includes: Traverse the abstract syntax tree and detect prototype chain operation nodes; For each of the prototype chain operation nodes, determine the prototype object to be assigned and the instance object to receive the assignment, and determine whether the prototype object has been marked as a tainted data source; When the prototype object has been marked as a tainted data source, an inheritance edge is added to the base data flow graph from the tainted data node of the prototype object to the tainted data node of the instance object. The inheritance edge is used to indicate the tainted propagation relationship on the prototype chain. When the prototype object is not marked as a tainted data source, a potential propagation edge is added to the basic data flow graph from the data node of the prototype object to the data node of the instance object, and the activation condition of the potential propagation edge is set to the prototype object being subsequently marked as a tainted data source.
5. The method according to claim 2, characterized in that, The process of identifying closure structures and generating closure variable reference edges includes: Traverse the abstract syntax tree, detect function definition nodes, perform free variable analysis for each function definition node, and obtain the external variables referenced by the function definition node that are not defined in its own parameter list or local variables as the set of free variables. Associate each external variable in the set of free variables with the location node inside the function definition node that uses that external variable; Perform escape analysis on the function definition node to determine whether the function definition node is returned, stored in the global object, or passed as a parameter to an external function. If the result of the escape analysis is that the function definition node escapes, then add a reference edge from the definition node of the external variable to the internal usage location node in the basic data flow graph. The reference edge is used to indicate the taint transit relationship of the closure capture variable. If the escape analysis results in the function definition node not escaping, then the reference edge is not added.
6. The method according to claim 2, characterized in that, The step of identifying asynchronous callback registrations and generating asynchronous control flow edges includes: traversing the abstract syntax tree and detecting asynchronous callback registration function call nodes; Obtain the callback function node from the asynchronous callback registration function call node; Determine the entry basic block of the callback function node; Detect whether there is a difference in event loop task queue type between the basic block where the asynchronous callback registration function call node is located and the entry basic block of the callback function node. The event loop task queue type includes macro task queue and micro task queue. Based on the differences in the event loop task queue types, an asynchronous control flow edge carrying a task type label is added to the basic control flow graph. The asynchronous control flow edge points from the basic block where the asynchronous callback registration function call node is located to the entry basic block of the callback function node. The task type label is used to indicate whether the callback function is executed in the macro task queue or the micro task queue.
7. The method according to claim 1, characterized in that, The preset vulnerability detection rule set includes multiple vulnerability patterns; each vulnerability pattern is associated with a taint source feature set and a taint convergence point feature set; The step of performing static taint analysis on the extended data flow graph and the extended control flow graph according to a preset vulnerability detection rule set to obtain a taint propagation path set further includes: Select the current vulnerability pattern from the preset vulnerability detection rule set; Based on the current vulnerability pattern, nodes that match the taint source feature set are identified from the extended data flow graph as taint source nodes; Based on the current vulnerability pattern, nodes that conform to the taint convergence point feature set are identified from the extended data flow graph as taint convergence point nodes.
8. The method according to claim 7, characterized in that, The step of performing static taint analysis on the extended data flow graph and the extended control flow graph according to a preset vulnerability detection rule set to obtain a taint propagation path set also includes: Based on the extended data flow graph, trace the data flow path that can reach the taint convergence point node from the taint source node, and record the data flow path as a candidate taint propagation path. Based on the extended control flow graph, the feasibility of the control flow in the candidate taint propagation path is verified, and the candidate taint propagation path that passes the verification is determined as the effective taint propagation path. The effective taint propagation paths are aggregated to obtain the taint propagation path set.
9. The method according to claim 8, characterized in that, The step of generating a vulnerability detection report based on the taint propagation path set includes: For each valid taint propagation path in the taint propagation path set, obtain the vulnerability pattern identifier corresponding to the path, the source code location information of the taint source node, the source code location information of the taint convergence node, and the sequence of intermediate nodes traversed by the path. A structured vulnerability report is generated based on the vulnerability pattern identifier, the source code location information, and the intermediate node sequence. The structured vulnerability report includes a vulnerability type field, a vulnerability trigger path field, and a vulnerability location field.
10. The method according to claim 2, characterized in that, After generating the abstract syntax tree, the process also includes: Perform cross-function call analysis on the abstract syntax tree, and associate the actual parameter nodes at the calling function with the formal parameter nodes of the called function according to the function call relationship graph, and add cross-function definition-use chains in the extended data flow graph; The cross-function call analysis includes: constructing a global function call graph, where the nodes of the function call graph are function definition nodes and the edges are call relationships; Identify higher-order function call patterns. When the actual argument itself is a function node, add a higher-order transitive edge from the return value node of the actual argument function to the formal parameter node of the called function in the extended data flow graph. Identify the parameter passing pattern of the callback function. When the actual parameter is a callback function node, add a reverse taint propagation edge from the parameter node inside the callback function node to the actual parameter node at the call point inside the called function in the extended data flow graph.