@@ -82,39 +82,50 @@ class MimetypeCall extends DataFlow::CallNode {
82
82
string getMimeType ( ) { mimeTypeMatches ( this .getExtension ( ) , result ) }
83
83
}
84
84
85
+ bindingset [ headerName]
86
+ private DataFlow:: Node getHeaderValue ( ResponseNode resp , string headerName ) {
87
+ exists ( DataFlow:: Node headers | headers = resp .getHeaders ( ) |
88
+ // set via `headers.<header_name>=`
89
+ exists (
90
+ DataFlow:: CallNode contentTypeAssignment , Assignment assignment ,
91
+ DataFlow:: PostUpdateNode postUpdateHeaders
92
+ |
93
+ contentTypeAssignment .getMethodName ( ) = headerName .replaceAll ( "-" , "_" ) .toLowerCase ( ) + "=" and
94
+ assignment =
95
+ contentTypeAssignment .getArgument ( 0 ) .( DataFlow:: OperationNode ) .asOperationAstNode ( ) and
96
+ postUpdateHeaders .( DataFlow:: LocalSourceNode ) .flowsTo ( headers ) and
97
+ postUpdateHeaders .getPreUpdateNode ( ) = contentTypeAssignment .getReceiver ( )
98
+ |
99
+ result .asExpr ( ) .getExpr ( ) = assignment .getRightOperand ( )
100
+ )
101
+ or
102
+ // set within a hash
103
+ exists ( DataFlow:: HashLiteralNode headersHash | headersHash .flowsTo ( headers ) |
104
+ result =
105
+ headersHash
106
+ .getElementFromKey ( any ( ConstantValue v |
107
+ v .getStringlikeValue ( ) .toLowerCase ( ) = headerName .toLowerCase ( )
108
+ ) )
109
+ )
110
+ )
111
+ }
112
+
85
113
/** A `DataFlow::Node` returned from a rack request. */
86
114
class ResponseNode extends PotentialResponseNode , Http:: Server:: HttpResponse:: Range {
87
115
ResponseNode ( ) { this = any ( AppCandidate app ) .getResponse ( ) }
88
116
89
117
override DataFlow:: Node getBody ( ) { result = this .getElement ( 2 ) }
90
118
91
119
override DataFlow:: Node getMimetypeOrContentTypeArg ( ) {
92
- exists ( DataFlow:: Node headers | headers = this .getHeaders ( ) |
93
- // set via `headers.content_type=`
94
- exists (
95
- DataFlow:: CallNode contentTypeAssignment , Assignment assignment ,
96
- DataFlow:: PostUpdateNode postUpdateHeaders
97
- |
98
- contentTypeAssignment .getMethodName ( ) = "content_type=" and
99
- assignment =
100
- contentTypeAssignment .getArgument ( 0 ) .( DataFlow:: OperationNode ) .asOperationAstNode ( ) and
101
- postUpdateHeaders .( DataFlow:: LocalSourceNode ) .flowsTo ( headers ) and
102
- postUpdateHeaders .getPreUpdateNode ( ) = contentTypeAssignment .getReceiver ( )
103
- |
104
- result .asExpr ( ) .getExpr ( ) = assignment .getRightOperand ( )
105
- )
106
- or
107
- // set within a hash
108
- exists ( DataFlow:: HashLiteralNode headersHash | headersHash .flowsTo ( headers ) |
109
- result =
110
- headersHash
111
- .getElementFromKey ( any ( ConstantValue v |
112
- v .getStringlikeValue ( ) .toLowerCase ( ) = "content-type"
113
- ) )
114
- )
115
- )
120
+ result = getHeaderValue ( this , "content-type" )
116
121
}
117
122
118
123
// TODO
119
124
override string getMimetypeDefault ( ) { none ( ) }
120
125
}
126
+
127
+ class RedirectResponse extends ResponseNode , Http:: Server:: HttpRedirectResponse:: Range {
128
+ RedirectResponse ( ) { this .getAStatusCode ( ) = [ 300 , 301 , 302 , 303 , 307 , 308 ] }
129
+
130
+ override DataFlow:: Node getRedirectLocation ( ) { result = getHeaderValue ( this , "location" ) }
131
+ }
0 commit comments