19
19
private import javascript
20
20
private import internal.ApiGraphModels as Shared
21
21
private import internal.ApiGraphModelsSpecific as Specific
22
+ private import semmle.javascript.dataflow.internal.FlowSummaryPrivate
22
23
private import semmle.javascript.endpoints.EndpointNaming as EndpointNaming
23
24
import Shared:: ModelInput as ModelInput
24
25
import Shared:: ModelOutput as ModelOutput
@@ -45,12 +46,50 @@ private class ThreatModelSourceFromDataExtension extends ThreatModelSource::Rang
45
46
}
46
47
}
47
48
49
+ private class SummarizedCallableFromModel extends DataFlow:: SummarizedCallable {
50
+ string type ;
51
+ string path ;
52
+
53
+ SummarizedCallableFromModel ( ) {
54
+ ModelOutput:: relevantSummaryModel ( type , path , _, _, _, _) and
55
+ this = type + ";" + path
56
+ }
57
+
58
+ override DataFlow:: InvokeNode getACall ( ) { ModelOutput:: resolvedSummaryBase ( type , path , result ) }
59
+
60
+ override predicate propagatesFlow (
61
+ string input , string output , boolean preservesValue , string model
62
+ ) {
63
+ exists ( string kind | ModelOutput:: relevantSummaryModel ( type , path , input , output , kind , model ) |
64
+ kind = "value" and
65
+ preservesValue = true
66
+ or
67
+ kind = "taint" and
68
+ preservesValue = false
69
+ )
70
+ }
71
+
72
+ predicate hasTypeAndPath ( string type_ , string path_ ) { type = type_ and path = path_ }
73
+
74
+ predicate isUnsupportedByFlowSummaries ( ) { unsupportedCallable ( this ) }
75
+ }
76
+
77
+ private predicate shouldInduceStepsFromSummary ( string type , string path ) {
78
+ exists ( SummarizedCallableFromModel callable |
79
+ callable .isUnsupportedByFlowSummaries ( ) and
80
+ callable .hasTypeAndPath ( type , path )
81
+ )
82
+ }
83
+
48
84
/**
49
85
* Holds if `path` is an input or output spec for a summary with the given `base` node.
50
86
*/
51
87
pragma [ nomagic]
52
88
private predicate relevantInputOutputPath ( API:: InvokeNode base , AccessPath inputOrOutput ) {
53
89
exists ( string type , string input , string output , string path |
90
+ // If the summary for 'callable' could not be handled as a flow summary, we need to evaluate
91
+ // its inputs and outputs to a set of nodes, so we can generate steps instead.
92
+ shouldInduceStepsFromSummary ( type , path ) and
54
93
ModelOutput:: resolvedSummaryBase ( type , path , base ) and
55
94
ModelOutput:: relevantSummaryModel ( type , path , input , output , _, _) and
56
95
inputOrOutput = [ input , output ]
@@ -81,6 +120,7 @@ private API::Node getNodeFromInputOutputPath(API::InvokeNode baseNode, AccessPat
81
120
82
121
private predicate summaryStep ( API:: Node pred , API:: Node succ , string kind ) {
83
122
exists ( string type , string path , API:: InvokeNode base , AccessPath input , AccessPath output |
123
+ shouldInduceStepsFromSummary ( type , path ) and
84
124
ModelOutput:: relevantSummaryModel ( type , path , input , output , kind , _) and
85
125
ModelOutput:: resolvedSummaryBase ( type , path , base ) and
86
126
pred = getNodeFromInputOutputPath ( base , input ) and
0 commit comments