Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit 0bf8064

Browse files
committed
Revel: mark header reads as user-controlled data
1 parent f0c0a89 commit 0bf8064

File tree

3 files changed

+40
-0
lines changed

3 files changed

+40
-0
lines changed

ql/src/semmle/go/frameworks/Revel.qll

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,4 +185,34 @@ module Revel {
185185

186186
override HTTP::ResponseWriter getResponseWriter() { none() }
187187
}
188+
189+
/**
190+
* The getter and setter methods of `revel.RevelHeader`.
191+
*
192+
* Note we currently don't implement `HeaderWrite` and related concepts, as they are currently only used
193+
* to track content-type, and directly setting headers does not seem to be the usual way to set the response
194+
* content-type for this framework. If and when the `HeaderWrite` concept has a more abstract idea of the
195+
* relationship between header-writes and HTTP responses than looking for a particular `http.ResponseWriter`
196+
* instance connecting the two, then we may implement it here for completeness.
197+
*/
198+
private class RevelHeaderMethods extends TaintTracking::FunctionModel {
199+
FunctionInput input;
200+
FunctionOutput output;
201+
string name;
202+
203+
RevelHeaderMethods() {
204+
this.(Method).hasQualifiedName(packagePath(), "RevelHeader", name) and
205+
(
206+
name = ["Add", "Set"] and input.isParameter([0, 1]) and output.isReceiver()
207+
or
208+
name = ["Get", "GetAll"] and input.isReceiver() and output.isResult()
209+
or
210+
name = "SetCookie" and input.isParameter(0) and output.isReceiver()
211+
)
212+
}
213+
214+
override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) {
215+
inp = input and outp = output
216+
}
217+
}
188218
}

ql/test/library-tests/semmle/go/frameworks/Revel/Revel.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,11 @@ func accessingServerRequest(c *revel.Controller) {
126126
c.Request.WebSocket.MessageReceiveJSON(&p) // NOT OK
127127
usePerson(p)
128128
}
129+
130+
func accessingHeaders(c *revel.Controller) {
131+
tainted := c.Request.Header.Get("somekey") // NOT OK
132+
useString(tainted)
133+
134+
tainted2 := c.Request.Header.GetAll("somekey") // NOT OK
135+
useString(tainted2[0])
136+
}

ql/test/library-tests/semmle/go/frameworks/Revel/TaintFlows.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,5 @@
3939
| Revel.go:117:12:117:32 | call to UserAgent | Revel.go:117:12:117:32 | call to UserAgent | 117 |
4040
| Revel.go:122:37:122:44 | &... : pointer type | Revel.go:123:12:123:18 | message | 122 |
4141
| Revel.go:126:41:126:42 | &... : pointer type | Revel.go:127:12:127:12 | p | 126 |
42+
| Revel.go:131:13:131:28 | selection of Header : pointer type | Revel.go:132:12:132:18 | tainted | 131 |
43+
| Revel.go:134:14:134:29 | selection of Header : pointer type | Revel.go:135:12:135:22 | index expression | 134 |

0 commit comments

Comments
 (0)