@grafema/core 0.1.0-alpha.4 → 0.1.1-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/dist/Orchestrator.d.ts +24 -2
- package/dist/Orchestrator.d.ts.map +1 -1
- package/dist/Orchestrator.js +197 -24
- package/dist/config/ConfigLoader.d.ts +72 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -0
- package/dist/config/ConfigLoader.js +187 -0
- package/dist/config/index.d.ts +6 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +4 -0
- package/dist/core/ASTWorker.d.ts +11 -36
- package/dist/core/ASTWorker.d.ts.map +1 -1
- package/dist/core/ASTWorker.js +93 -99
- package/dist/core/CoverageAnalyzer.d.ts +65 -0
- package/dist/core/CoverageAnalyzer.d.ts.map +1 -0
- package/dist/core/CoverageAnalyzer.js +198 -0
- package/dist/core/FileNodeManager.d.ts +40 -0
- package/dist/core/FileNodeManager.d.ts.map +1 -0
- package/dist/core/FileNodeManager.js +84 -0
- package/dist/core/GraphFreshnessChecker.d.ts +33 -0
- package/dist/core/GraphFreshnessChecker.d.ts.map +1 -0
- package/dist/core/GraphFreshnessChecker.js +101 -0
- package/dist/core/HashUtils.d.ts +24 -0
- package/dist/core/HashUtils.d.ts.map +1 -0
- package/dist/core/HashUtils.js +45 -0
- package/dist/core/IncrementalReanalyzer.d.ts +36 -0
- package/dist/core/IncrementalReanalyzer.d.ts.map +1 -0
- package/dist/core/IncrementalReanalyzer.js +132 -0
- package/dist/core/NodeFactory.d.ts +225 -17
- package/dist/core/NodeFactory.d.ts.map +1 -1
- package/dist/core/NodeFactory.js +208 -18
- package/dist/core/ScopeTracker.d.ts +84 -0
- package/dist/core/ScopeTracker.d.ts.map +1 -0
- package/dist/core/ScopeTracker.js +116 -0
- package/dist/core/SemanticId.d.ts +90 -0
- package/dist/core/SemanticId.d.ts.map +1 -0
- package/dist/core/SemanticId.js +115 -0
- package/dist/core/VersionManager.d.ts.map +1 -1
- package/dist/core/VersionManager.js +3 -2
- package/dist/core/nodes/ArgumentExpressionNode.d.ts +43 -0
- package/dist/core/nodes/ArgumentExpressionNode.d.ts.map +1 -0
- package/dist/core/nodes/ArgumentExpressionNode.js +60 -0
- package/dist/core/nodes/ArrayLiteralNode.d.ts +27 -0
- package/dist/core/nodes/ArrayLiteralNode.d.ts.map +1 -0
- package/dist/core/nodes/ArrayLiteralNode.js +41 -0
- package/dist/core/nodes/CallSiteNode.d.ts +28 -0
- package/dist/core/nodes/CallSiteNode.d.ts.map +1 -1
- package/dist/core/nodes/CallSiteNode.js +46 -0
- package/dist/core/nodes/ClassNode.d.ts +33 -1
- package/dist/core/nodes/ClassNode.d.ts.map +1 -1
- package/dist/core/nodes/ClassNode.js +46 -2
- package/dist/core/nodes/DecoratorNode.d.ts +42 -0
- package/dist/core/nodes/DecoratorNode.d.ts.map +1 -0
- package/dist/core/nodes/DecoratorNode.js +62 -0
- package/dist/core/nodes/EnumNode.d.ts +42 -0
- package/dist/core/nodes/EnumNode.d.ts.map +1 -0
- package/dist/core/nodes/EnumNode.js +54 -0
- package/dist/core/nodes/ExportNode.d.ts +37 -1
- package/dist/core/nodes/ExportNode.d.ts.map +1 -1
- package/dist/core/nodes/ExportNode.js +48 -2
- package/dist/core/nodes/ExpressionNode.d.ts +97 -0
- package/dist/core/nodes/ExpressionNode.d.ts.map +1 -0
- package/dist/core/nodes/ExpressionNode.js +178 -0
- package/dist/core/nodes/ExternalModuleNode.d.ts +28 -0
- package/dist/core/nodes/ExternalModuleNode.d.ts.map +1 -0
- package/dist/core/nodes/ExternalModuleNode.js +41 -0
- package/dist/core/nodes/ExternalStdioNode.d.ts +13 -6
- package/dist/core/nodes/ExternalStdioNode.d.ts.map +1 -1
- package/dist/core/nodes/ExternalStdioNode.js +15 -8
- package/dist/core/nodes/FunctionNode.d.ts +36 -0
- package/dist/core/nodes/FunctionNode.d.ts.map +1 -1
- package/dist/core/nodes/FunctionNode.js +80 -1
- package/dist/core/nodes/ImportNode.d.ts +19 -5
- package/dist/core/nodes/ImportNode.d.ts.map +1 -1
- package/dist/core/nodes/ImportNode.js +23 -5
- package/dist/core/nodes/InterfaceNode.d.ts +46 -0
- package/dist/core/nodes/InterfaceNode.d.ts.map +1 -0
- package/dist/core/nodes/InterfaceNode.js +55 -0
- package/dist/core/nodes/IssueNode.d.ts +73 -0
- package/dist/core/nodes/IssueNode.d.ts.map +1 -0
- package/dist/core/nodes/IssueNode.js +129 -0
- package/dist/core/nodes/MethodCallNode.d.ts +30 -0
- package/dist/core/nodes/MethodCallNode.d.ts.map +1 -1
- package/dist/core/nodes/MethodCallNode.js +49 -0
- package/dist/core/nodes/MethodNode.d.ts +32 -0
- package/dist/core/nodes/MethodNode.d.ts.map +1 -1
- package/dist/core/nodes/MethodNode.js +48 -0
- package/dist/core/nodes/ModuleNode.d.ts +31 -0
- package/dist/core/nodes/ModuleNode.d.ts.map +1 -1
- package/dist/core/nodes/ModuleNode.js +37 -0
- package/dist/core/nodes/NetworkRequestNode.d.ts +54 -0
- package/dist/core/nodes/NetworkRequestNode.d.ts.map +1 -0
- package/dist/core/nodes/NetworkRequestNode.js +65 -0
- package/dist/core/nodes/ObjectLiteralNode.d.ts +27 -0
- package/dist/core/nodes/ObjectLiteralNode.d.ts.map +1 -0
- package/dist/core/nodes/ObjectLiteralNode.js +41 -0
- package/dist/core/nodes/ScopeNode.d.ts +31 -0
- package/dist/core/nodes/ScopeNode.d.ts.map +1 -1
- package/dist/core/nodes/ScopeNode.js +49 -0
- package/dist/core/nodes/TypeNode.d.ts +36 -0
- package/dist/core/nodes/TypeNode.d.ts.map +1 -0
- package/dist/core/nodes/TypeNode.js +53 -0
- package/dist/core/nodes/VariableDeclarationNode.d.ts +27 -0
- package/dist/core/nodes/VariableDeclarationNode.d.ts.map +1 -1
- package/dist/core/nodes/VariableDeclarationNode.js +40 -0
- package/dist/core/nodes/index.d.ts +12 -1
- package/dist/core/nodes/index.d.ts.map +1 -1
- package/dist/core/nodes/index.js +14 -0
- package/dist/diagnostics/DiagnosticCollector.d.ts +98 -0
- package/dist/diagnostics/DiagnosticCollector.d.ts.map +1 -0
- package/dist/diagnostics/DiagnosticCollector.js +129 -0
- package/dist/diagnostics/DiagnosticReporter.d.ts +77 -0
- package/dist/diagnostics/DiagnosticReporter.d.ts.map +1 -0
- package/dist/diagnostics/DiagnosticReporter.js +159 -0
- package/dist/diagnostics/DiagnosticWriter.d.ts +31 -0
- package/dist/diagnostics/DiagnosticWriter.d.ts.map +1 -0
- package/dist/diagnostics/DiagnosticWriter.js +43 -0
- package/dist/diagnostics/index.d.ts +14 -0
- package/dist/diagnostics/index.d.ts.map +1 -0
- package/dist/diagnostics/index.js +11 -0
- package/dist/errors/GrafemaError.d.ts +118 -0
- package/dist/errors/GrafemaError.d.ts.map +1 -0
- package/dist/errors/GrafemaError.js +131 -0
- package/dist/index.d.ts +57 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +54 -1
- package/dist/logging/Logger.d.ts +48 -0
- package/dist/logging/Logger.d.ts.map +1 -0
- package/dist/logging/Logger.js +134 -0
- package/dist/plugins/Plugin.d.ts +5 -1
- package/dist/plugins/Plugin.d.ts.map +1 -1
- package/dist/plugins/Plugin.js +33 -0
- package/dist/plugins/analysis/DatabaseAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/DatabaseAnalyzer.js +13 -6
- package/dist/plugins/analysis/ExpressAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/ExpressAnalyzer.js +27 -19
- package/dist/plugins/analysis/ExpressRouteAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/ExpressRouteAnalyzer.js +21 -14
- package/dist/plugins/analysis/FetchAnalyzer.d.ts +1 -0
- package/dist/plugins/analysis/FetchAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/FetchAnalyzer.js +34 -14
- package/dist/plugins/analysis/IncrementalAnalysisPlugin.d.ts +6 -3
- package/dist/plugins/analysis/IncrementalAnalysisPlugin.d.ts.map +1 -1
- package/dist/plugins/analysis/IncrementalAnalysisPlugin.js +76 -80
- package/dist/plugins/analysis/JSASTAnalyzer.d.ts +180 -17
- package/dist/plugins/analysis/JSASTAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/JSASTAnalyzer.js +1171 -471
- package/dist/plugins/analysis/ReactAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/ReactAnalyzer.js +56 -57
- package/dist/plugins/analysis/RustAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/RustAnalyzer.js +15 -10
- package/dist/plugins/analysis/SQLiteAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/SQLiteAnalyzer.js +9 -7
- package/dist/plugins/analysis/ServiceLayerAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/ServiceLayerAnalyzer.js +21 -9
- package/dist/plugins/analysis/SocketIOAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/SocketIOAnalyzer.js +27 -15
- package/dist/plugins/analysis/SystemDbAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/SystemDbAnalyzer.js +15 -5
- package/dist/plugins/analysis/ast/GraphBuilder.d.ts +34 -4
- package/dist/plugins/analysis/ast/GraphBuilder.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/GraphBuilder.js +318 -298
- package/dist/plugins/analysis/ast/IdGenerator.d.ts +105 -0
- package/dist/plugins/analysis/ast/IdGenerator.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/IdGenerator.js +116 -0
- package/dist/plugins/analysis/ast/types.d.ts +176 -5
- package/dist/plugins/analysis/ast/types.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/utils/createParameterNodes.d.ts +33 -0
- package/dist/plugins/analysis/ast/utils/createParameterNodes.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/utils/createParameterNodes.js +89 -0
- package/dist/plugins/analysis/ast/utils/index.d.ts +6 -0
- package/dist/plugins/analysis/ast/utils/index.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/utils/index.js +5 -0
- package/dist/plugins/analysis/ast/utils/location.d.ts +87 -0
- package/dist/plugins/analysis/ast/utils/location.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/utils/location.js +78 -0
- package/dist/plugins/analysis/ast/visitors/ASTVisitor.d.ts +9 -4
- package/dist/plugins/analysis/ast/visitors/ASTVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/ASTVisitor.js +6 -5
- package/dist/plugins/analysis/ast/visitors/CallExpressionVisitor.d.ts +99 -9
- package/dist/plugins/analysis/ast/visitors/CallExpressionVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/CallExpressionVisitor.js +663 -125
- package/dist/plugins/analysis/ast/visitors/ClassVisitor.d.ts +4 -1
- package/dist/plugins/analysis/ast/visitors/ClassVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/ClassVisitor.js +72 -32
- package/dist/plugins/analysis/ast/visitors/FunctionVisitor.d.ts +4 -1
- package/dist/plugins/analysis/ast/visitors/FunctionVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/FunctionVisitor.js +128 -63
- package/dist/plugins/analysis/ast/visitors/ImportExportVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/ImportExportVisitor.js +11 -8
- package/dist/plugins/analysis/ast/visitors/TypeScriptVisitor.d.ts +12 -1
- package/dist/plugins/analysis/ast/visitors/TypeScriptVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/TypeScriptVisitor.js +36 -14
- package/dist/plugins/analysis/ast/visitors/VariableVisitor.d.ts +4 -1
- package/dist/plugins/analysis/ast/visitors/VariableVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/VariableVisitor.js +17 -13
- package/dist/plugins/discovery/MonorepoServiceDiscovery.d.ts.map +1 -1
- package/dist/plugins/discovery/MonorepoServiceDiscovery.js +3 -2
- package/dist/plugins/discovery/SimpleProjectDiscovery.d.ts.map +1 -1
- package/dist/plugins/discovery/SimpleProjectDiscovery.js +5 -1
- package/dist/plugins/discovery/WorkspaceDiscovery.d.ts +22 -0
- package/dist/plugins/discovery/WorkspaceDiscovery.d.ts.map +1 -0
- package/dist/plugins/discovery/WorkspaceDiscovery.js +136 -0
- package/dist/plugins/discovery/resolveSourceEntrypoint.d.ts +46 -0
- package/dist/plugins/discovery/resolveSourceEntrypoint.d.ts.map +1 -0
- package/dist/plugins/discovery/resolveSourceEntrypoint.js +86 -0
- package/dist/plugins/discovery/workspaces/detector.d.ts +21 -0
- package/dist/plugins/discovery/workspaces/detector.d.ts.map +1 -0
- package/dist/plugins/discovery/workspaces/detector.js +49 -0
- package/dist/plugins/discovery/workspaces/globResolver.d.ts +35 -0
- package/dist/plugins/discovery/workspaces/globResolver.d.ts.map +1 -0
- package/dist/plugins/discovery/workspaces/globResolver.js +184 -0
- package/dist/plugins/discovery/workspaces/index.d.ts +9 -0
- package/dist/plugins/discovery/workspaces/index.d.ts.map +1 -0
- package/dist/plugins/discovery/workspaces/index.js +8 -0
- package/dist/plugins/discovery/workspaces/parsers.d.ts +38 -0
- package/dist/plugins/discovery/workspaces/parsers.d.ts.map +1 -0
- package/dist/plugins/discovery/workspaces/parsers.js +80 -0
- package/dist/plugins/enrichment/AliasTracker.d.ts.map +1 -1
- package/dist/plugins/enrichment/AliasTracker.js +14 -8
- package/dist/plugins/enrichment/HTTPConnectionEnricher.d.ts.map +1 -1
- package/dist/plugins/enrichment/HTTPConnectionEnricher.js +14 -7
- package/dist/plugins/enrichment/ImportExportLinker.d.ts.map +1 -1
- package/dist/plugins/enrichment/ImportExportLinker.js +23 -6
- package/dist/plugins/enrichment/MethodCallResolver.d.ts.map +1 -1
- package/dist/plugins/enrichment/MethodCallResolver.js +18 -12
- package/dist/plugins/enrichment/MountPointResolver.d.ts.map +1 -1
- package/dist/plugins/enrichment/MountPointResolver.js +8 -3
- package/dist/plugins/enrichment/PrefixEvaluator.d.ts.map +1 -1
- package/dist/plugins/enrichment/PrefixEvaluator.js +16 -7
- package/dist/plugins/enrichment/RustFFIEnricher.d.ts.map +1 -1
- package/dist/plugins/enrichment/RustFFIEnricher.js +6 -5
- package/dist/plugins/enrichment/ValueDomainAnalyzer.d.ts +17 -0
- package/dist/plugins/enrichment/ValueDomainAnalyzer.d.ts.map +1 -1
- package/dist/plugins/enrichment/ValueDomainAnalyzer.js +129 -10
- package/dist/plugins/indexing/IncrementalModuleIndexer.d.ts.map +1 -1
- package/dist/plugins/indexing/IncrementalModuleIndexer.js +23 -14
- package/dist/plugins/indexing/JSModuleIndexer.d.ts.map +1 -1
- package/dist/plugins/indexing/JSModuleIndexer.js +63 -31
- package/dist/plugins/indexing/RustModuleIndexer.d.ts.map +1 -1
- package/dist/plugins/indexing/RustModuleIndexer.js +5 -4
- package/dist/plugins/indexing/ServiceDetector.d.ts +10 -0
- package/dist/plugins/indexing/ServiceDetector.d.ts.map +1 -1
- package/dist/plugins/indexing/ServiceDetector.js +28 -15
- package/dist/plugins/validation/CallResolverValidator.d.ts.map +1 -1
- package/dist/plugins/validation/CallResolverValidator.js +8 -7
- package/dist/plugins/validation/DataFlowValidator.d.ts.map +1 -1
- package/dist/plugins/validation/DataFlowValidator.js +17 -12
- package/dist/plugins/validation/EvalBanValidator.d.ts.map +1 -1
- package/dist/plugins/validation/EvalBanValidator.js +17 -16
- package/dist/plugins/validation/GraphConnectivityValidator.d.ts.map +1 -1
- package/dist/plugins/validation/GraphConnectivityValidator.js +19 -23
- package/dist/plugins/validation/NodeCreationValidator.d.ts +85 -0
- package/dist/plugins/validation/NodeCreationValidator.d.ts.map +1 -0
- package/dist/plugins/validation/NodeCreationValidator.js +415 -0
- package/dist/plugins/validation/SQLInjectionValidator.d.ts.map +1 -1
- package/dist/plugins/validation/SQLInjectionValidator.js +59 -16
- package/dist/plugins/validation/ShadowingDetector.d.ts.map +1 -1
- package/dist/plugins/validation/ShadowingDetector.js +6 -5
- package/dist/plugins/validation/TypeScriptDeadCodeValidator.d.ts.map +1 -1
- package/dist/plugins/validation/TypeScriptDeadCodeValidator.js +12 -11
- package/dist/plugins/vcs/GitPlugin.d.ts.map +1 -1
- package/dist/plugins/vcs/GitPlugin.js +10 -12
- package/dist/plugins/vcs/VCSPlugin.d.ts +3 -2
- package/dist/plugins/vcs/VCSPlugin.d.ts.map +1 -1
- package/dist/plugins/vcs/VCSPlugin.js +5 -5
- package/dist/storage/backends/RFDBServerBackend.d.ts +10 -17
- package/dist/storage/backends/RFDBServerBackend.d.ts.map +1 -1
- package/dist/storage/backends/RFDBServerBackend.js +31 -10
- package/dist/validation/PathValidator.d.ts +1 -2
- package/dist/validation/PathValidator.d.ts.map +1 -1
- package/package.json +6 -3
- package/src/Orchestrator.ts +237 -24
- package/src/config/ConfigLoader.ts +263 -0
- package/src/config/index.ts +5 -0
- package/src/core/ASTWorker.ts +143 -139
- package/src/core/CoverageAnalyzer.ts +243 -0
- package/src/core/FileNodeManager.ts +100 -0
- package/src/core/GraphFreshnessChecker.ts +143 -0
- package/src/core/HashUtils.ts +48 -0
- package/src/core/IncrementalReanalyzer.ts +192 -0
- package/src/core/NodeFactory.ts +401 -18
- package/src/core/ScopeTracker.ts +154 -0
- package/src/core/SemanticId.ts +192 -0
- package/src/core/VersionManager.ts +3 -2
- package/src/core/nodes/ArgumentExpressionNode.ts +89 -0
- package/src/core/nodes/ArrayLiteralNode.ts +65 -0
- package/src/core/nodes/CallSiteNode.ts +58 -0
- package/src/core/nodes/ClassNode.ts +63 -2
- package/src/core/nodes/DecoratorNode.ts +91 -0
- package/src/core/nodes/EnumNode.ts +86 -0
- package/src/core/nodes/ExportNode.ts +70 -2
- package/src/core/nodes/ExpressionNode.ts +231 -0
- package/src/core/nodes/ExternalModuleNode.ts +56 -0
- package/src/core/nodes/ExternalStdioNode.ts +17 -9
- package/src/core/nodes/FunctionNode.ts +101 -1
- package/src/core/nodes/ImportNode.ts +32 -10
- package/src/core/nodes/InterfaceNode.ts +91 -0
- package/src/core/nodes/IssueNode.ts +177 -0
- package/src/core/nodes/MethodCallNode.ts +64 -0
- package/src/core/nodes/MethodNode.ts +63 -0
- package/src/core/nodes/ModuleNode.ts +50 -0
- package/src/core/nodes/NetworkRequestNode.ts +77 -0
- package/src/core/nodes/ObjectLiteralNode.ts +65 -0
- package/src/core/nodes/ScopeNode.ts +65 -0
- package/src/core/nodes/TypeNode.ts +78 -0
- package/src/core/nodes/VariableDeclarationNode.ts +52 -0
- package/src/core/nodes/index.ts +18 -1
- package/src/diagnostics/DiagnosticCollector.ts +163 -0
- package/src/diagnostics/DiagnosticReporter.ts +204 -0
- package/src/diagnostics/DiagnosticWriter.ts +50 -0
- package/src/diagnostics/index.ts +16 -0
- package/src/errors/GrafemaError.ts +174 -0
- package/src/index.ts +148 -1
- package/src/logging/Logger.ts +152 -0
- package/src/plugins/Plugin.ts +42 -0
- package/src/plugins/analysis/DatabaseAnalyzer.ts +14 -8
- package/src/plugins/analysis/ExpressAnalyzer.ts +29 -19
- package/src/plugins/analysis/ExpressRouteAnalyzer.ts +22 -21
- package/src/plugins/analysis/FetchAnalyzer.ts +39 -16
- package/src/plugins/analysis/IncrementalAnalysisPlugin.ts +84 -101
- package/src/plugins/analysis/JSASTAnalyzer.ts +1483 -503
- package/src/plugins/analysis/ReactAnalyzer.ts +57 -57
- package/src/plugins/analysis/RustAnalyzer.ts +15 -10
- package/src/plugins/analysis/SQLiteAnalyzer.ts +10 -7
- package/src/plugins/analysis/ServiceLayerAnalyzer.ts +22 -16
- package/src/plugins/analysis/SocketIOAnalyzer.ts +31 -22
- package/src/plugins/analysis/SystemDbAnalyzer.ts +16 -11
- package/src/plugins/analysis/ast/GraphBuilder.ts +439 -327
- package/src/plugins/analysis/ast/IdGenerator.ts +177 -0
- package/src/plugins/analysis/ast/types.ts +209 -6
- package/src/plugins/analysis/ast/utils/createParameterNodes.ts +104 -0
- package/src/plugins/analysis/ast/utils/index.ts +12 -0
- package/src/plugins/analysis/ast/utils/location.ts +103 -0
- package/src/plugins/analysis/ast/visitors/ASTVisitor.ts +11 -8
- package/src/plugins/analysis/ast/visitors/CallExpressionVisitor.ts +909 -83
- package/src/plugins/analysis/ast/visitors/ClassVisitor.ts +97 -44
- package/src/plugins/analysis/ast/visitors/FunctionVisitor.ts +159 -93
- package/src/plugins/analysis/ast/visitors/ImportExportVisitor.ts +12 -8
- package/src/plugins/analysis/ast/visitors/TypeScriptVisitor.ts +41 -14
- package/src/plugins/analysis/ast/visitors/VariableVisitor.ts +37 -17
- package/src/plugins/discovery/MonorepoServiceDiscovery.ts +3 -2
- package/src/plugins/discovery/SimpleProjectDiscovery.ts +6 -1
- package/src/plugins/discovery/WorkspaceDiscovery.ts +177 -0
- package/src/plugins/discovery/resolveSourceEntrypoint.ts +103 -0
- package/src/plugins/discovery/workspaces/detector.ts +63 -0
- package/src/plugins/discovery/workspaces/globResolver.ts +229 -0
- package/src/plugins/discovery/workspaces/index.ts +23 -0
- package/src/plugins/discovery/workspaces/parsers.ts +99 -0
- package/src/plugins/enrichment/AliasTracker.ts +14 -8
- package/src/plugins/enrichment/HTTPConnectionEnricher.ts +14 -7
- package/src/plugins/enrichment/ImportExportLinker.ts +24 -6
- package/src/plugins/enrichment/MethodCallResolver.ts +18 -12
- package/src/plugins/enrichment/MountPointResolver.ts +8 -3
- package/src/plugins/enrichment/PrefixEvaluator.ts +16 -7
- package/src/plugins/enrichment/RustFFIEnricher.ts +6 -5
- package/src/plugins/enrichment/ValueDomainAnalyzer.ts +149 -12
- package/src/plugins/indexing/IncrementalModuleIndexer.ts +23 -14
- package/src/plugins/indexing/JSModuleIndexer.ts +74 -34
- package/src/plugins/indexing/RustModuleIndexer.ts +5 -4
- package/src/plugins/validation/CallResolverValidator.ts +8 -7
- package/src/plugins/validation/DataFlowValidator.ts +16 -12
- package/src/plugins/validation/EvalBanValidator.ts +17 -16
- package/src/plugins/validation/GraphConnectivityValidator.ts +19 -23
- package/src/plugins/validation/NodeCreationValidator.ts +554 -0
- package/src/plugins/validation/SQLInjectionValidator.ts +61 -15
- package/src/plugins/validation/ShadowingDetector.ts +6 -5
- package/src/plugins/validation/TypeScriptDeadCodeValidator.ts +12 -11
- package/src/plugins/vcs/GitPlugin.ts +40 -12
- package/src/plugins/vcs/VCSPlugin.ts +7 -5
- package/src/storage/backends/RFDBServerBackend.ts +43 -29
- package/src/validation/PathValidator.ts +1 -1
- package/dist/core/AnalysisWorker.d.ts +0 -14
- package/dist/core/AnalysisWorker.d.ts.map +0 -1
- package/dist/core/AnalysisWorker.js +0 -307
- package/dist/core/ParallelAnalyzer.d.ts +0 -120
- package/dist/core/ParallelAnalyzer.d.ts.map +0 -1
- package/dist/core/ParallelAnalyzer.js +0 -331
- package/dist/core/QueueWorker.d.ts +0 -12
- package/dist/core/QueueWorker.d.ts.map +0 -1
- package/dist/core/QueueWorker.js +0 -567
- package/dist/core/RFDBClient.d.ts +0 -179
- package/dist/core/RFDBClient.d.ts.map +0 -1
- package/dist/core/RFDBClient.js +0 -429
- package/dist/plugins/discovery/ZonServiceDiscovery.d.ts +0 -19
- package/dist/plugins/discovery/ZonServiceDiscovery.d.ts.map +0 -1
- package/dist/plugins/discovery/ZonServiceDiscovery.js +0 -204
- package/src/core/AnalysisWorker.ts +0 -410
- package/src/core/ParallelAnalyzer.ts +0 -476
- package/src/core/QueueWorker.ts +0 -780
- package/src/plugins/indexing/ServiceDetector.ts +0 -230
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NodeCreationValidator - validates that nodes are created through NodeFactory
|
|
3
|
+
*
|
|
4
|
+
* GUARANTEE: All nodes passed to graph.addNode() or graph.addNodes() must be
|
|
5
|
+
* created through NodeFactory methods, not constructed inline.
|
|
6
|
+
*
|
|
7
|
+
* This validator uses the data flow tracking (HAS_PROPERTY, HAS_ELEMENT, FLOWS_INTO edges)
|
|
8
|
+
* to trace object literals back to their source and verify they come from
|
|
9
|
+
* NodeFactory calls.
|
|
10
|
+
*
|
|
11
|
+
* FLOWS_INTO traversal: When an array variable is passed to addNodes(), we check:
|
|
12
|
+
* 1. Static array contents via HAS_ELEMENT edges
|
|
13
|
+
* 2. Dynamic array contents via FLOWS_INTO edges (from push, unshift, splice, indexed assignment)
|
|
14
|
+
*
|
|
15
|
+
* DATALOG RULES (conceptual):
|
|
16
|
+
*
|
|
17
|
+
* % Find all calls to addNodes (batch)
|
|
18
|
+
* add_nodes_call(Call) :-
|
|
19
|
+
* node(Call, "CALL"),
|
|
20
|
+
* attr(Call, "name", "addNodes").
|
|
21
|
+
*
|
|
22
|
+
* % Find array argument passed to addNodes (arg 0)
|
|
23
|
+
* add_nodes_array(Call, Arr) :-
|
|
24
|
+
* add_nodes_call(Call),
|
|
25
|
+
* edge(Call, Arr, "PASSES_ARGUMENT"),
|
|
26
|
+
* node(Arr, "ARRAY_LITERAL").
|
|
27
|
+
*
|
|
28
|
+
* % Find objects inside the array (static elements)
|
|
29
|
+
* add_nodes_object(Call, Obj) :-
|
|
30
|
+
* add_nodes_array(Call, Arr),
|
|
31
|
+
* edge(Arr, Obj, "HAS_ELEMENT"),
|
|
32
|
+
* node(Obj, "OBJECT_LITERAL").
|
|
33
|
+
*
|
|
34
|
+
* % Find objects pushed/unshifted/spliced into array (dynamic elements)
|
|
35
|
+
* add_nodes_object(Call, Obj) :-
|
|
36
|
+
* add_nodes_call(Call),
|
|
37
|
+
* edge(Call, ArrVar, "PASSES_ARGUMENT"),
|
|
38
|
+
* node(ArrVar, "VARIABLE"),
|
|
39
|
+
* incoming(ArrVar, Obj, "FLOWS_INTO"), % value --FLOWS_INTO--> array
|
|
40
|
+
* node(Obj, "OBJECT_LITERAL").
|
|
41
|
+
*
|
|
42
|
+
* % Object created via NodeFactory
|
|
43
|
+
* from_node_factory(Obj) :-
|
|
44
|
+
* incoming(Obj, Creator, "ASSIGNED_FROM"),
|
|
45
|
+
* node(Creator, "CALL"),
|
|
46
|
+
* attr(Creator, "object", "NodeFactory").
|
|
47
|
+
*
|
|
48
|
+
* % Violation: object in addNodes not from NodeFactory
|
|
49
|
+
* violation_batch(Call, Obj) :-
|
|
50
|
+
* add_nodes_object(Call, Obj),
|
|
51
|
+
* \+ from_node_factory(Obj).
|
|
52
|
+
*/
|
|
53
|
+
import { Plugin, createSuccessResult } from '../Plugin.js';
|
|
54
|
+
export class NodeCreationValidator extends Plugin {
|
|
55
|
+
get metadata() {
|
|
56
|
+
return {
|
|
57
|
+
name: 'NodeCreationValidator',
|
|
58
|
+
phase: 'VALIDATION',
|
|
59
|
+
priority: 90, // Run after data flow analysis
|
|
60
|
+
creates: {
|
|
61
|
+
nodes: [],
|
|
62
|
+
edges: []
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
async execute(context) {
|
|
67
|
+
const { graph } = context;
|
|
68
|
+
const logger = this.log(context);
|
|
69
|
+
logger.info('Starting NodeFactory usage validation');
|
|
70
|
+
const startTime = Date.now();
|
|
71
|
+
const issues = [];
|
|
72
|
+
let addNodeCalls = 0;
|
|
73
|
+
let addNodesCalls = 0;
|
|
74
|
+
let inlineObjects = 0;
|
|
75
|
+
let factoryObjects = 0;
|
|
76
|
+
let unknownObjects = 0;
|
|
77
|
+
// Check if graph supports required methods
|
|
78
|
+
if (!graph.getAllEdges || !graph.getAllNodes) {
|
|
79
|
+
logger.debug('Graph does not support getAllEdges/getAllNodes, skipping validation');
|
|
80
|
+
return createSuccessResult({ nodes: 0, edges: 0 }, { skipped: true });
|
|
81
|
+
}
|
|
82
|
+
const allNodes = await graph.getAllNodes();
|
|
83
|
+
const allEdges = await graph.getAllEdges();
|
|
84
|
+
// Build lookup maps for efficient queries
|
|
85
|
+
const nodesById = new Map();
|
|
86
|
+
for (const node of allNodes) {
|
|
87
|
+
nodesById.set(node.id, node);
|
|
88
|
+
}
|
|
89
|
+
const edgesBySrc = new Map();
|
|
90
|
+
const edgesByDst = new Map();
|
|
91
|
+
for (const edge of allEdges) {
|
|
92
|
+
if (!edgesBySrc.has(edge.src))
|
|
93
|
+
edgesBySrc.set(edge.src, []);
|
|
94
|
+
edgesBySrc.get(edge.src).push(edge);
|
|
95
|
+
if (!edgesByDst.has(edge.dst))
|
|
96
|
+
edgesByDst.set(edge.dst, []);
|
|
97
|
+
edgesByDst.get(edge.dst).push(edge);
|
|
98
|
+
}
|
|
99
|
+
// 1. Find all calls to addNode and addNodes
|
|
100
|
+
logger.debug('Searching for addNode/addNodes calls');
|
|
101
|
+
for (const node of allNodes) {
|
|
102
|
+
if (node.type !== 'CALL')
|
|
103
|
+
continue;
|
|
104
|
+
const callNode = node;
|
|
105
|
+
// Check for addNode() method call
|
|
106
|
+
if (callNode.method === 'addNode' || callNode.name === 'addNode' ||
|
|
107
|
+
(callNode.name && callNode.name.endsWith('.addNode'))) {
|
|
108
|
+
addNodeCalls++;
|
|
109
|
+
const argIssues = await this.validateAddNodeCall(callNode, edgesBySrc, edgesByDst, nodesById);
|
|
110
|
+
issues.push(...argIssues);
|
|
111
|
+
}
|
|
112
|
+
// Check for addNodes() method call
|
|
113
|
+
if (callNode.method === 'addNodes' || callNode.name === 'addNodes' ||
|
|
114
|
+
(callNode.name && callNode.name.endsWith('.addNodes'))) {
|
|
115
|
+
addNodesCalls++;
|
|
116
|
+
const argIssues = await this.validateAddNodesCall(callNode, edgesBySrc, edgesByDst, nodesById);
|
|
117
|
+
issues.push(...argIssues);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Count violation types
|
|
121
|
+
for (const issue of issues) {
|
|
122
|
+
if (issue.type === 'INLINE_OBJECT_LITERAL' || issue.type === 'INLINE_ARRAY_ELEMENT') {
|
|
123
|
+
inlineObjects++;
|
|
124
|
+
}
|
|
125
|
+
else if (issue.type === 'UNKNOWN_SOURCE') {
|
|
126
|
+
unknownObjects++;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const totalTime = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
130
|
+
const summary = {
|
|
131
|
+
addNodeCalls,
|
|
132
|
+
addNodesCalls,
|
|
133
|
+
inlineObjects,
|
|
134
|
+
factoryObjects, // Would need positive tracking to count
|
|
135
|
+
unknownObjects,
|
|
136
|
+
totalViolations: issues.length,
|
|
137
|
+
timeSeconds: totalTime
|
|
138
|
+
};
|
|
139
|
+
logger.info('Validation complete', { ...summary });
|
|
140
|
+
if (issues.length > 0) {
|
|
141
|
+
logger.warn('NodeFactory violations found', { count: issues.length });
|
|
142
|
+
for (const issue of issues.slice(0, 10)) { // Limit output
|
|
143
|
+
logger.warn(`[${issue.type}] ${issue.message}`, { suggestion: issue.suggestion });
|
|
144
|
+
}
|
|
145
|
+
if (issues.length > 10) {
|
|
146
|
+
logger.debug(`... and ${issues.length - 10} more violations`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
logger.info('All nodes created through NodeFactory');
|
|
151
|
+
}
|
|
152
|
+
return createSuccessResult({ nodes: 0, edges: 0 }, { summary, issues });
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Validate a single addNode(node) call
|
|
156
|
+
*/
|
|
157
|
+
async validateAddNodeCall(callNode, edgesBySrc, edgesByDst, nodesById) {
|
|
158
|
+
const issues = [];
|
|
159
|
+
// Find PASSES_ARGUMENT edge (arg 0)
|
|
160
|
+
const passedArgs = edgesBySrc.get(callNode.id)?.filter(e => e.type === 'PASSES_ARGUMENT') || [];
|
|
161
|
+
for (const argEdge of passedArgs) {
|
|
162
|
+
const argNode = nodesById.get(argEdge.dst);
|
|
163
|
+
if (!argNode)
|
|
164
|
+
continue;
|
|
165
|
+
// Check if it's an inline object literal
|
|
166
|
+
if (argNode.type === 'OBJECT_LITERAL') {
|
|
167
|
+
const isFromFactory = this.isFromNodeFactory(argNode.id, edgesByDst, nodesById);
|
|
168
|
+
if (!isFromFactory) {
|
|
169
|
+
issues.push({
|
|
170
|
+
type: 'INLINE_OBJECT_LITERAL',
|
|
171
|
+
severity: 'ERROR',
|
|
172
|
+
message: `Inline object literal passed to addNode() at ${callNode.file}:${callNode.line}`,
|
|
173
|
+
callSiteId: callNode.id,
|
|
174
|
+
objectId: argNode.id,
|
|
175
|
+
file: callNode.file,
|
|
176
|
+
line: callNode.line,
|
|
177
|
+
suggestion: 'Use NodeFactory.createX() to create the node instead of an inline object'
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Check if it's a variable - trace its origin
|
|
182
|
+
if (argNode.type === 'VARIABLE' || argNode.type === 'VARIABLE_DECLARATION') {
|
|
183
|
+
const source = this.traceVariableSource(argNode.id, edgesBySrc, nodesById);
|
|
184
|
+
if (source && source.type === 'OBJECT_LITERAL') {
|
|
185
|
+
const isFromFactory = this.isFromNodeFactory(source.id, edgesByDst, nodesById);
|
|
186
|
+
if (!isFromFactory) {
|
|
187
|
+
issues.push({
|
|
188
|
+
type: 'INLINE_OBJECT_LITERAL',
|
|
189
|
+
severity: 'ERROR',
|
|
190
|
+
message: `Variable "${argNode.name}" assigned from inline object literal, passed to addNode() at ${callNode.file}:${callNode.line}`,
|
|
191
|
+
callSiteId: callNode.id,
|
|
192
|
+
objectId: source.id,
|
|
193
|
+
file: callNode.file,
|
|
194
|
+
line: callNode.line,
|
|
195
|
+
suggestion: 'Use NodeFactory.createX() to create the node instead of an inline object'
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return issues;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Validate addNodes([...]) call
|
|
205
|
+
* Also checks for objects that flow into arrays via FLOWS_INTO edges
|
|
206
|
+
*/
|
|
207
|
+
async validateAddNodesCall(callNode, edgesBySrc, edgesByDst, nodesById) {
|
|
208
|
+
const issues = [];
|
|
209
|
+
// Find PASSES_ARGUMENT edge (arg 0 - the array)
|
|
210
|
+
const passedArgs = edgesBySrc.get(callNode.id)?.filter(e => e.type === 'PASSES_ARGUMENT') || [];
|
|
211
|
+
for (const argEdge of passedArgs) {
|
|
212
|
+
const argNode = nodesById.get(argEdge.dst);
|
|
213
|
+
if (!argNode)
|
|
214
|
+
continue;
|
|
215
|
+
// Check if it's an array literal
|
|
216
|
+
if (argNode.type === 'ARRAY_LITERAL') {
|
|
217
|
+
// Find all HAS_ELEMENT edges
|
|
218
|
+
const elements = edgesBySrc.get(argNode.id)?.filter(e => e.type === 'HAS_ELEMENT') || [];
|
|
219
|
+
for (const elemEdge of elements) {
|
|
220
|
+
const elemNode = nodesById.get(elemEdge.dst);
|
|
221
|
+
if (!elemNode)
|
|
222
|
+
continue;
|
|
223
|
+
// Check if element is an inline object literal
|
|
224
|
+
if (elemNode.type === 'OBJECT_LITERAL') {
|
|
225
|
+
const isFromFactory = this.isFromNodeFactory(elemNode.id, edgesByDst, nodesById);
|
|
226
|
+
if (!isFromFactory) {
|
|
227
|
+
const elemIndex = elemEdge.metadata?.elementIndex ?? '?';
|
|
228
|
+
issues.push({
|
|
229
|
+
type: 'INLINE_ARRAY_ELEMENT',
|
|
230
|
+
severity: 'ERROR',
|
|
231
|
+
message: `Inline object literal at index ${elemIndex} in addNodes() array at ${callNode.file}:${callNode.line}`,
|
|
232
|
+
callSiteId: callNode.id,
|
|
233
|
+
objectId: elemNode.id,
|
|
234
|
+
file: callNode.file,
|
|
235
|
+
line: callNode.line,
|
|
236
|
+
suggestion: 'Use NodeFactory.createX() to create each node in the array'
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
// Check if element is a variable - trace its origin
|
|
241
|
+
if (elemNode.type === 'VARIABLE' || elemNode.type === 'VARIABLE_DECLARATION') {
|
|
242
|
+
const source = this.traceVariableSource(elemNode.id, edgesBySrc, nodesById);
|
|
243
|
+
if (source && source.type === 'OBJECT_LITERAL') {
|
|
244
|
+
const isFromFactory = this.isFromNodeFactory(source.id, edgesByDst, nodesById);
|
|
245
|
+
if (!isFromFactory) {
|
|
246
|
+
const elemIndex = elemEdge.metadata?.elementIndex ?? '?';
|
|
247
|
+
issues.push({
|
|
248
|
+
type: 'INLINE_ARRAY_ELEMENT',
|
|
249
|
+
severity: 'ERROR',
|
|
250
|
+
message: `Variable "${elemNode.name}" at index ${elemIndex} assigned from inline object, passed to addNodes() at ${callNode.file}:${callNode.line}`,
|
|
251
|
+
callSiteId: callNode.id,
|
|
252
|
+
objectId: source.id,
|
|
253
|
+
file: callNode.file,
|
|
254
|
+
line: callNode.line,
|
|
255
|
+
suggestion: 'Use NodeFactory.createX() to create the node'
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// Check if it's a variable containing an array
|
|
263
|
+
if (argNode.type === 'VARIABLE' || argNode.type === 'VARIABLE_DECLARATION') {
|
|
264
|
+
// Check what flows INTO this variable (array mutations via push/unshift/splice/indexed)
|
|
265
|
+
const incomingFlows = this.getArrayContents(argNode.id, edgesByDst, nodesById);
|
|
266
|
+
for (const sourceNode of incomingFlows) {
|
|
267
|
+
// Check if the pushed value is an object literal
|
|
268
|
+
if (sourceNode.type === 'OBJECT_LITERAL') {
|
|
269
|
+
const isFromFactory = this.isFromNodeFactory(sourceNode.id, edgesByDst, nodesById);
|
|
270
|
+
if (!isFromFactory) {
|
|
271
|
+
issues.push({
|
|
272
|
+
type: 'INLINE_ARRAY_ELEMENT',
|
|
273
|
+
severity: 'ERROR',
|
|
274
|
+
message: `Object pushed into array "${argNode.name}" is not from NodeFactory, passed to addNodes() at ${callNode.file}:${callNode.line}`,
|
|
275
|
+
callSiteId: callNode.id,
|
|
276
|
+
objectId: sourceNode.id,
|
|
277
|
+
file: callNode.file,
|
|
278
|
+
line: callNode.line,
|
|
279
|
+
suggestion: 'Use NodeFactory.createX() to create nodes before pushing to array'
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// Also trace if the pushed value is a variable
|
|
284
|
+
if (sourceNode.type === 'VARIABLE' || sourceNode.type === 'VARIABLE_DECLARATION') {
|
|
285
|
+
const source = this.traceVariableSource(sourceNode.id, edgesBySrc, nodesById);
|
|
286
|
+
if (source && source.type === 'OBJECT_LITERAL') {
|
|
287
|
+
const isFromFactory = this.isFromNodeFactory(source.id, edgesByDst, nodesById);
|
|
288
|
+
if (!isFromFactory) {
|
|
289
|
+
issues.push({
|
|
290
|
+
type: 'INLINE_ARRAY_ELEMENT',
|
|
291
|
+
severity: 'ERROR',
|
|
292
|
+
message: `Variable "${sourceNode.name}" pushed into array "${argNode.name}" is not from NodeFactory, passed to addNodes() at ${callNode.file}:${callNode.line}`,
|
|
293
|
+
callSiteId: callNode.id,
|
|
294
|
+
objectId: source.id,
|
|
295
|
+
file: callNode.file,
|
|
296
|
+
line: callNode.line,
|
|
297
|
+
suggestion: 'Use NodeFactory.createX() to create the node'
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
// Also check static array contents (HAS_ELEMENT) - existing logic
|
|
304
|
+
const source = this.traceVariableSource(argNode.id, edgesBySrc, nodesById);
|
|
305
|
+
if (source && source.type === 'ARRAY_LITERAL') {
|
|
306
|
+
// Recursively check array elements
|
|
307
|
+
const elements = edgesBySrc.get(source.id)?.filter(e => e.type === 'HAS_ELEMENT') || [];
|
|
308
|
+
for (const elemEdge of elements) {
|
|
309
|
+
const elemNode = nodesById.get(elemEdge.dst);
|
|
310
|
+
if (!elemNode)
|
|
311
|
+
continue;
|
|
312
|
+
if (elemNode.type === 'OBJECT_LITERAL') {
|
|
313
|
+
const isFromFactory = this.isFromNodeFactory(elemNode.id, edgesByDst, nodesById);
|
|
314
|
+
if (!isFromFactory) {
|
|
315
|
+
const elemIndex = elemEdge.metadata?.elementIndex ?? '?';
|
|
316
|
+
issues.push({
|
|
317
|
+
type: 'INLINE_ARRAY_ELEMENT',
|
|
318
|
+
severity: 'ERROR',
|
|
319
|
+
message: `Inline object at index ${elemIndex} in array "${argNode.name}" passed to addNodes() at ${callNode.file}:${callNode.line}`,
|
|
320
|
+
callSiteId: callNode.id,
|
|
321
|
+
objectId: elemNode.id,
|
|
322
|
+
file: callNode.file,
|
|
323
|
+
line: callNode.line,
|
|
324
|
+
suggestion: 'Use NodeFactory.createX() to create each node in the array'
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return issues;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Get all nodes that flow INTO an array variable via FLOWS_INTO edges
|
|
336
|
+
* These are objects/values that were pushed, unshifted, spliced, or assigned to the array
|
|
337
|
+
*
|
|
338
|
+
* Edge direction: value --FLOWS_INTO--> array
|
|
339
|
+
* So we look for INCOMING edges where dst === arrayNodeId
|
|
340
|
+
*/
|
|
341
|
+
getArrayContents(arrayNodeId, edgesByDst, nodesById) {
|
|
342
|
+
const contents = [];
|
|
343
|
+
// Find INCOMING FLOWS_INTO edges to this array
|
|
344
|
+
const incomingFlows = edgesByDst.get(arrayNodeId)?.filter(e => e.type === 'FLOWS_INTO') || [];
|
|
345
|
+
for (const edge of incomingFlows) {
|
|
346
|
+
const sourceNode = nodesById.get(edge.src);
|
|
347
|
+
if (sourceNode) {
|
|
348
|
+
contents.push(sourceNode);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return contents;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Check if a node is created from NodeFactory
|
|
355
|
+
* Traces ASSIGNED_FROM edges to find the source call
|
|
356
|
+
*/
|
|
357
|
+
isFromNodeFactory(nodeId, edgesByDst, nodesById, visited = new Set()) {
|
|
358
|
+
if (visited.has(nodeId))
|
|
359
|
+
return false;
|
|
360
|
+
visited.add(nodeId);
|
|
361
|
+
// Find incoming ASSIGNED_FROM edges
|
|
362
|
+
const incomingEdges = edgesByDst.get(nodeId)?.filter(e => e.type === 'ASSIGNED_FROM') || [];
|
|
363
|
+
for (const edge of incomingEdges) {
|
|
364
|
+
const sourceNode = nodesById.get(edge.src);
|
|
365
|
+
if (!sourceNode)
|
|
366
|
+
continue;
|
|
367
|
+
// Check if source is a CALL to NodeFactory
|
|
368
|
+
if (sourceNode.type === 'CALL') {
|
|
369
|
+
const callNode = sourceNode;
|
|
370
|
+
// Check various ways NodeFactory calls can appear
|
|
371
|
+
if (callNode.object === 'NodeFactory' ||
|
|
372
|
+
callNode.name?.startsWith('NodeFactory.') ||
|
|
373
|
+
callNode.name === 'NodeFactory') {
|
|
374
|
+
return true;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
// Continue tracing through variables
|
|
378
|
+
if (sourceNode.type === 'VARIABLE' || sourceNode.type === 'VARIABLE_DECLARATION') {
|
|
379
|
+
if (this.isFromNodeFactory(sourceNode.id, edgesByDst, nodesById, visited)) {
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Trace a variable back to its source node (through ASSIGNED_FROM edges)
|
|
388
|
+
*/
|
|
389
|
+
traceVariableSource(nodeId, edgesBySrc, nodesById, visited = new Set()) {
|
|
390
|
+
if (visited.has(nodeId))
|
|
391
|
+
return null;
|
|
392
|
+
visited.add(nodeId);
|
|
393
|
+
// Find outgoing ASSIGNED_FROM edges (variable -> source)
|
|
394
|
+
const outgoingEdges = edgesBySrc.get(nodeId)?.filter(e => e.type === 'ASSIGNED_FROM') || [];
|
|
395
|
+
for (const edge of outgoingEdges) {
|
|
396
|
+
const targetNode = nodesById.get(edge.dst);
|
|
397
|
+
if (!targetNode)
|
|
398
|
+
continue;
|
|
399
|
+
// If target is a literal/call/object, return it
|
|
400
|
+
if (targetNode.type === 'OBJECT_LITERAL' ||
|
|
401
|
+
targetNode.type === 'ARRAY_LITERAL' ||
|
|
402
|
+
targetNode.type === 'CALL' ||
|
|
403
|
+
targetNode.type === 'LITERAL') {
|
|
404
|
+
return targetNode;
|
|
405
|
+
}
|
|
406
|
+
// Continue tracing through variables
|
|
407
|
+
if (targetNode.type === 'VARIABLE' || targetNode.type === 'VARIABLE_DECLARATION') {
|
|
408
|
+
const source = this.traceVariableSource(targetNode.id, edgesBySrc, nodesById, visited);
|
|
409
|
+
if (source)
|
|
410
|
+
return source;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SQLInjectionValidator.d.ts","sourceRoot":"","sources":["../../../src/plugins/validation/SQLInjectionValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,MAAM,EAAuB,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAsEhF,qBAAa,qBAAsB,SAAQ,MAAM;IAC/C,OAAO,CAAC,aAAa,CAAsB;;IAO3C,IAAI,QAAQ,IAAI,cAAc,CAU7B;IAEK,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"SQLInjectionValidator.d.ts","sourceRoot":"","sources":["../../../src/plugins/validation/SQLInjectionValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,MAAM,EAAuB,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAsEhF,qBAAa,qBAAsB,SAAQ,MAAM;IAC/C,OAAO,CAAC,aAAa,CAAsB;;IAO3C,IAAI,QAAQ,IAAI,cAAc,CAU7B;IAEK,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAgH5D;;OAEG;YACW,gBAAgB;IAgF9B;;OAEG;YACW,gCAAgC;IAsC9C;;;OAGG;YACW,oBAAoB;CAsDnC;AAED,eAAe,qBAAqB,CAAC"}
|
|
@@ -34,15 +34,18 @@ export class SQLInjectionValidator extends Plugin {
|
|
|
34
34
|
phase: 'VALIDATION',
|
|
35
35
|
priority: 90, // After ValueDomainAnalyzer (65)
|
|
36
36
|
creates: {
|
|
37
|
-
nodes: [],
|
|
38
|
-
edges: []
|
|
37
|
+
nodes: ['issue:security'],
|
|
38
|
+
edges: ['AFFECTS']
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
async execute(context) {
|
|
43
43
|
const { graph } = context;
|
|
44
|
-
|
|
44
|
+
const logger = this.log(context);
|
|
45
|
+
logger.info('Starting SQL injection vulnerability check');
|
|
45
46
|
const issues = [];
|
|
47
|
+
let issueNodeCount = 0;
|
|
48
|
+
let affectsEdgeCount = 0;
|
|
46
49
|
// 1. Find all CALL nodes that look like SQL queries
|
|
47
50
|
const sqlCalls = [];
|
|
48
51
|
for await (const node of graph.queryNodes({ nodeType: 'CALL' })) {
|
|
@@ -52,12 +55,12 @@ export class SQLInjectionValidator extends Plugin {
|
|
|
52
55
|
sqlCalls.push(callNode);
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
|
-
|
|
58
|
+
logger.debug('SQL calls collected', { count: sqlCalls.length });
|
|
56
59
|
// 2. For each SQL call, analyze the query argument
|
|
57
60
|
for (const call of sqlCalls) {
|
|
58
61
|
const result = await this.analyzeQueryCall(call, graph);
|
|
59
62
|
if (result.isVulnerable) {
|
|
60
|
-
|
|
63
|
+
const issue = {
|
|
61
64
|
type: 'SQL_INJECTION',
|
|
62
65
|
severity: 'ERROR',
|
|
63
66
|
message: `Potential SQL injection at ${call.file}:${call.line || '?'} - ${result.reason}`,
|
|
@@ -66,32 +69,72 @@ export class SQLInjectionValidator extends Plugin {
|
|
|
66
69
|
line: call.line,
|
|
67
70
|
reason: result.reason,
|
|
68
71
|
nondeterministicSources: result.sources
|
|
69
|
-
}
|
|
72
|
+
};
|
|
73
|
+
issues.push(issue);
|
|
74
|
+
// Persist issue to graph if reportIssue is available
|
|
75
|
+
if (context.reportIssue) {
|
|
76
|
+
await context.reportIssue({
|
|
77
|
+
category: 'security',
|
|
78
|
+
severity: 'error',
|
|
79
|
+
message: issue.message,
|
|
80
|
+
file: call.file || '',
|
|
81
|
+
line: call.line || 0,
|
|
82
|
+
column: call.column || 0,
|
|
83
|
+
targetNodeId: call.id,
|
|
84
|
+
context: {
|
|
85
|
+
type: 'SQL_INJECTION',
|
|
86
|
+
reason: result.reason,
|
|
87
|
+
nondeterministicSources: result.sources
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
issueNodeCount++;
|
|
91
|
+
affectsEdgeCount++;
|
|
92
|
+
}
|
|
70
93
|
}
|
|
71
94
|
}
|
|
72
95
|
// 3. Also check via graph pattern - CALL nodes that have ARGUMENT -> PARAMETER paths
|
|
73
|
-
const patternViolations = await this.checkViaGraphPattern(graph, sqlCalls);
|
|
96
|
+
const patternViolations = await this.checkViaGraphPattern(graph, logger, sqlCalls);
|
|
74
97
|
for (const violation of patternViolations) {
|
|
75
98
|
// Avoid duplicates
|
|
76
99
|
if (!issues.find(i => i.nodeId === violation.nodeId)) {
|
|
77
100
|
issues.push(violation);
|
|
101
|
+
// Persist issue to graph if reportIssue is available
|
|
102
|
+
if (context.reportIssue) {
|
|
103
|
+
await context.reportIssue({
|
|
104
|
+
category: 'security',
|
|
105
|
+
severity: 'error',
|
|
106
|
+
message: violation.message,
|
|
107
|
+
file: violation.file || '',
|
|
108
|
+
line: violation.line || 0,
|
|
109
|
+
targetNodeId: violation.nodeId,
|
|
110
|
+
context: {
|
|
111
|
+
type: 'SQL_INJECTION',
|
|
112
|
+
reason: violation.reason,
|
|
113
|
+
nondeterministicSources: violation.nondeterministicSources
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
issueNodeCount++;
|
|
117
|
+
affectsEdgeCount++;
|
|
118
|
+
}
|
|
78
119
|
}
|
|
79
120
|
}
|
|
80
121
|
const summary = {
|
|
81
122
|
sqlCallsChecked: sqlCalls.length,
|
|
82
|
-
vulnerabilitiesFound: issues.length
|
|
123
|
+
vulnerabilitiesFound: issues.length,
|
|
124
|
+
issueNodesCreated: issueNodeCount,
|
|
125
|
+
affectsEdgesCreated: affectsEdgeCount
|
|
83
126
|
};
|
|
84
|
-
|
|
127
|
+
logger.info('Validation complete', summary);
|
|
85
128
|
if (issues.length > 0) {
|
|
86
|
-
|
|
129
|
+
logger.warn('SQL injection vulnerabilities found', { count: issues.length });
|
|
87
130
|
for (const issue of issues) {
|
|
88
|
-
|
|
131
|
+
logger.warn(issue.message);
|
|
89
132
|
}
|
|
90
133
|
}
|
|
91
134
|
else {
|
|
92
|
-
|
|
135
|
+
logger.info('No SQL injection vulnerabilities detected');
|
|
93
136
|
}
|
|
94
|
-
return createSuccessResult({ nodes:
|
|
137
|
+
return createSuccessResult({ nodes: issueNodeCount, edges: affectsEdgeCount }, { summary, issues });
|
|
95
138
|
}
|
|
96
139
|
/**
|
|
97
140
|
* Analyze a SQL query call for injection vulnerabilities
|
|
@@ -200,14 +243,14 @@ export class SQLInjectionValidator extends Plugin {
|
|
|
200
243
|
* Check via Datalog graph pattern for SQL injection
|
|
201
244
|
* Pattern: CALL -[PASSES_ARGUMENT]-> VARIABLE -[ASSIGNED_FROM*]-> PARAMETER
|
|
202
245
|
*/
|
|
203
|
-
async checkViaGraphPattern(graph, excludeCalls = []) {
|
|
246
|
+
async checkViaGraphPattern(graph, logger, excludeCalls = []) {
|
|
204
247
|
const issues = [];
|
|
205
248
|
const excludeIds = new Set(excludeCalls.map(c => c.id));
|
|
206
249
|
// Find CALL nodes that have argument tracing to PARAMETER
|
|
207
250
|
try {
|
|
208
251
|
// Check if graph supports checkGuarantee
|
|
209
252
|
if (!graph.checkGuarantee) {
|
|
210
|
-
|
|
253
|
+
logger.debug('Graph does not support checkGuarantee, skipping pattern-based check');
|
|
211
254
|
return issues;
|
|
212
255
|
}
|
|
213
256
|
// Check guarantee for SQL method calls with parameter-derived arguments
|
|
@@ -243,7 +286,7 @@ export class SQLInjectionValidator extends Plugin {
|
|
|
243
286
|
}
|
|
244
287
|
catch (err) {
|
|
245
288
|
// Datalog query might fail if backend doesn't support it
|
|
246
|
-
|
|
289
|
+
logger.debug('Datalog check skipped', { error: err.message });
|
|
247
290
|
}
|
|
248
291
|
return issues;
|
|
249
292
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShadowingDetector.d.ts","sourceRoot":"","sources":["../../../src/plugins/validation/ShadowingDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,MAAM,EAAuB,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAoChF,qBAAa,iBAAkB,SAAQ,MAAM;IAC3C,IAAI,QAAQ,IAAI,cAAc,CAU7B;IAEK,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"ShadowingDetector.d.ts","sourceRoot":"","sources":["../../../src/plugins/validation/ShadowingDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,MAAM,EAAuB,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAoChF,qBAAa,iBAAkB,SAAQ,MAAM;IAC3C,IAAI,QAAQ,IAAI,cAAc,CAU7B;IAEK,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;CAuG7D"}
|
|
@@ -32,7 +32,8 @@ export class ShadowingDetector extends Plugin {
|
|
|
32
32
|
}
|
|
33
33
|
async execute(context) {
|
|
34
34
|
const { graph } = context;
|
|
35
|
-
|
|
35
|
+
const logger = this.log(context);
|
|
36
|
+
logger.info('Starting variable shadowing detection');
|
|
36
37
|
const issues = [];
|
|
37
38
|
// Get all relevant nodes
|
|
38
39
|
const allClasses = await graph.getAllNodes({ type: 'CLASS' });
|
|
@@ -104,15 +105,15 @@ export class ShadowingDetector extends Plugin {
|
|
|
104
105
|
scopeShadows: scopeCount,
|
|
105
106
|
totalIssues: issues.length
|
|
106
107
|
};
|
|
107
|
-
|
|
108
|
+
logger.info('Detection complete', { ...summary });
|
|
108
109
|
if (issues.length > 0) {
|
|
109
|
-
|
|
110
|
+
logger.warn('Shadowing issues found', { count: issues.length });
|
|
110
111
|
for (const issue of issues) {
|
|
111
|
-
|
|
112
|
+
logger.warn(issue.message, { type: issue.type });
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
else {
|
|
115
|
-
|
|
116
|
+
logger.info('No shadowing issues detected');
|
|
116
117
|
}
|
|
117
118
|
return createSuccessResult({ nodes: 0, edges: 0 }, { summary, issues });
|
|
118
119
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TypeScriptDeadCodeValidator.d.ts","sourceRoot":"","sources":["../../../src/plugins/validation/TypeScriptDeadCodeValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,MAAM,EAAuB,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AA4BhF,qBAAa,2BAA4B,SAAQ,MAAM;IACrD,IAAI,QAAQ,IAAI,cAAc,CAW7B;IAEK,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"TypeScriptDeadCodeValidator.d.ts","sourceRoot":"","sources":["../../../src/plugins/validation/TypeScriptDeadCodeValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,MAAM,EAAuB,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AA4BhF,qBAAa,2BAA4B,SAAQ,MAAM;IACrD,IAAI,QAAQ,IAAI,cAAc,CAW7B;IAEK,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;CAiJ7D"}
|