1919private import javascript
2020private import internal.ApiGraphModels as Shared
2121private import internal.ApiGraphModelsSpecific as Specific
22+ private import semmle.javascript.dataflow.internal.FlowSummaryPrivate
2223private import semmle.javascript.endpoints.EndpointNaming as EndpointNaming
2324import Shared:: ModelInput as ModelInput
2425import Shared:: ModelOutput as ModelOutput
@@ -45,12 +46,50 @@ private class ThreatModelSourceFromDataExtension extends ThreatModelSource::Rang
4546 }
4647}
4748
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+
4884/**
4985 * Holds if `path` is an input or output spec for a summary with the given `base` node.
5086 */
5187pragma [ nomagic]
5288private predicate relevantInputOutputPath ( API:: InvokeNode base , AccessPath inputOrOutput ) {
5389 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
5493 ModelOutput:: resolvedSummaryBase ( type , path , base ) and
5594 ModelOutput:: relevantSummaryModel ( type , path , input , output , _, _) and
5695 inputOrOutput = [ input , output ]
@@ -81,6 +120,7 @@ private API::Node getNodeFromInputOutputPath(API::InvokeNode baseNode, AccessPat
81120
82121private predicate summaryStep ( API:: Node pred , API:: Node succ , string kind ) {
83122 exists ( string type , string path , API:: InvokeNode base , AccessPath input , AccessPath output |
123+ shouldInduceStepsFromSummary ( type , path ) and
84124 ModelOutput:: relevantSummaryModel ( type , path , input , output , kind , _) and
85125 ModelOutput:: resolvedSummaryBase ( type , path , base ) and
86126 pred = getNodeFromInputOutputPath ( base , input ) and
0 commit comments