Skip to content

Commit 06fac54

Browse files
committed
Add web framework: github.com/gofiber/fiber
1 parent 8796666 commit 06fac54

23 files changed

+1463
-0
lines changed
Lines changed: 398 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,398 @@
1+
/**
2+
* Provides classes for working with concepts from the following packages:
3+
* - [`github.com/gofiber/fiber@v1.14.6`](https://pkg.go.dev/github.com/gofiber/fiber@v1.14.6)
4+
* - [`github.com/gofiber/utils@v0.1.0`](https://pkg.go.dev/github.com/gofiber/utils@v0.1.0)
5+
*/
6+
7+
import go
8+
9+
/**
10+
* Provides classes for working with concepts from the following packages:
11+
* - [`github.com/gofiber/fiber@v1.14.6`](https://pkg.go.dev/github.com/gofiber/fiber@v1.14.6)
12+
* - [`github.com/gofiber/utils@v0.1.0`](https://pkg.go.dev/github.com/gofiber/utils@v0.1.0)
13+
*/
14+
private module Fiber {
15+
/**
16+
* Models taint-tracking through functions.
17+
*/
18+
private class TaintTrackingFunctionModels extends TaintTracking::FunctionModel {
19+
FunctionInput inp;
20+
FunctionOutput out;
21+
22+
TaintTrackingFunctionModels() {
23+
// Taint-tracking models for package: github.com/gofiber/fiber@v1.14.6
24+
// signature: func NewError(code int, message ...string) *Error
25+
this.hasQualifiedName(package("github.com/gofiber/fiber", ""), "NewError") and
26+
inp.isParameter(any(int i | i >= 1)) and
27+
out.isResult()
28+
or
29+
// Taint-tracking models for package: github.com/gofiber/utils@v0.1.0
30+
(
31+
// signature: func GetBytes(s string) []byte
32+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "GetBytes") and
33+
inp.isParameter(0) and
34+
out.isResult()
35+
or
36+
// signature: func GetString(b []byte) string
37+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "GetString") and
38+
inp.isParameter(0) and
39+
out.isResult()
40+
or
41+
// signature: func ImmutableString(s string) string
42+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "ImmutableString") and
43+
inp.isParameter(0) and
44+
out.isResult()
45+
or
46+
// signature: func SafeBytes(b []byte) []byte
47+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "SafeBytes") and
48+
inp.isParameter(0) and
49+
out.isResult()
50+
or
51+
// signature: func SafeString(s string) string
52+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "SafeString") and
53+
inp.isParameter(0) and
54+
out.isResult()
55+
or
56+
// signature: func ToLower(b string) string
57+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "ToLower") and
58+
inp.isParameter(0) and
59+
out.isResult()
60+
or
61+
// signature: func ToLowerBytes(b []byte) []byte
62+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "ToLowerBytes") and
63+
inp.isParameter(0) and
64+
out.isResult()
65+
or
66+
// signature: func ToUpper(b string) string
67+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "ToUpper") and
68+
inp.isParameter(0) and
69+
out.isResult()
70+
or
71+
// signature: func ToUpperBytes(b []byte) []byte
72+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "ToUpperBytes") and
73+
inp.isParameter(0) and
74+
out.isResult()
75+
or
76+
// signature: func Trim(s string, cutset byte) string
77+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "Trim") and
78+
inp.isParameter(0) and
79+
out.isResult()
80+
or
81+
// signature: func TrimBytes(b []byte, cutset byte) []byte
82+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "TrimBytes") and
83+
inp.isParameter(0) and
84+
out.isResult()
85+
or
86+
// signature: func TrimLeft(s string, cutset byte) string
87+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "TrimLeft") and
88+
inp.isParameter(0) and
89+
out.isResult()
90+
or
91+
// signature: func TrimLeftBytes(b []byte, cutset byte) []byte
92+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "TrimLeftBytes") and
93+
inp.isParameter(0) and
94+
out.isResult()
95+
or
96+
// signature: func TrimRight(s string, cutset byte) string
97+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "TrimRight") and
98+
inp.isParameter(0) and
99+
out.isResult()
100+
or
101+
// signature: func TrimRightBytes(b []byte, cutset byte) []byte
102+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "TrimRightBytes") and
103+
inp.isParameter(0) and
104+
out.isResult()
105+
or
106+
// signature: func UnsafeBytes(s string) (bs []byte)
107+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "UnsafeBytes") and
108+
inp.isParameter(0) and
109+
out.isResult()
110+
or
111+
// signature: func UnsafeString(b []byte) string
112+
this.hasQualifiedName(package("github.com/gofiber/utils", ""), "UnsafeString") and
113+
inp.isParameter(0) and
114+
out.isResult()
115+
)
116+
}
117+
118+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
119+
input = inp and output = out
120+
}
121+
}
122+
123+
/**
124+
* Models HTTP redirects.
125+
*/
126+
private class Redirect extends HTTP::Redirect::Range, DataFlow::CallNode {
127+
string package;
128+
DataFlow::Node urlNode;
129+
130+
Redirect() {
131+
// HTTP redirect models for package: github.com/gofiber/fiber@v1.14.6
132+
package = package("github.com/gofiber/fiber", "") and
133+
// Receiver type: Ctx
134+
(
135+
// signature: func (*Ctx).Redirect(location string, status ...int)
136+
this = any(Method m | m.hasQualifiedName(package, "Ctx", "Redirect")).getACall() and
137+
urlNode = this.getArgument(0)
138+
)
139+
}
140+
141+
override DataFlow::Node getUrl() { result = urlNode }
142+
143+
override HTTP::ResponseWriter getResponseWriter() { result.getANode() = this.getReceiver() }
144+
}
145+
146+
/**
147+
* Models HTTP header writers.
148+
* The write is done with a call where you can set both the key and the value of the header.
149+
*/
150+
private class HeaderWrite extends HTTP::HeaderWrite::Range, DataFlow::CallNode {
151+
DataFlow::Node receiverNode;
152+
DataFlow::Node headerNameNode;
153+
DataFlow::Node headerValueNode;
154+
155+
HeaderWrite() {
156+
setsHeaderDynamicKeyValue(_, _, this, headerNameNode, headerValueNode, receiverNode)
157+
}
158+
159+
override DataFlow::Node getName() { result = headerNameNode }
160+
161+
override DataFlow::Node getValue() { result = headerValueNode }
162+
163+
override HTTP::ResponseWriter getResponseWriter() { result.getANode() = receiverNode }
164+
}
165+
166+
// Holds for a call that sets a header with a key-value combination.
167+
private predicate setsHeaderDynamicKeyValue(
168+
string package, string receiverName, DataFlow::CallNode headerSetterCall,
169+
DataFlow::Node headerNameNode, DataFlow::Node headerValueNode, DataFlow::Node receiverNode
170+
) {
171+
exists(string methodName, Method met |
172+
met.hasQualifiedName(package, receiverName, methodName) and
173+
headerSetterCall = met.getACall() and
174+
receiverNode = headerSetterCall.getReceiver()
175+
|
176+
package = package("github.com/gofiber/fiber", "") and
177+
(
178+
// Receiver type: Ctx
179+
receiverName = "Ctx" and
180+
(
181+
// signature: func (*Ctx).Append(field string, values ...string)
182+
methodName = "Append" and
183+
headerNameNode = headerSetterCall.getArgument(0) and
184+
headerValueNode = headerSetterCall.getArgument(any(int i | i >= 1))
185+
or
186+
// signature: func (*Ctx).Set(key string, val string)
187+
methodName = "Set" and
188+
headerNameNode = headerSetterCall.getArgument(0) and
189+
headerValueNode = headerSetterCall.getArgument(1)
190+
)
191+
)
192+
)
193+
}
194+
195+
/**
196+
* Models HTTP ResponseBody where the content-type is static and non-modifiable.
197+
*/
198+
private class ResponseBodyStaticContentType extends HTTP::ResponseBody::Range {
199+
string contentTypeString;
200+
DataFlow::Node receiverNode;
201+
202+
ResponseBodyStaticContentType() {
203+
exists(string package, string receiverName |
204+
setsBodyAndStaticContentType(package, receiverName, this, contentTypeString, receiverNode)
205+
)
206+
}
207+
208+
override string getAContentType() { result = contentTypeString }
209+
210+
override HTTP::ResponseWriter getResponseWriter() { result.getANode() = receiverNode }
211+
}
212+
213+
// Holds for a call that sets the body; the content-type is implicitly set.
214+
private predicate setsBodyAndStaticContentType(
215+
string package, string receiverName, DataFlow::Node bodyNode, string contentTypeString,
216+
DataFlow::Node receiverNode
217+
) {
218+
exists(string methodName, Method met, DataFlow::CallNode bodySetterCall |
219+
met.hasQualifiedName(package, receiverName, methodName) and
220+
bodySetterCall = met.getACall() and
221+
receiverNode = bodySetterCall.getReceiver()
222+
|
223+
package = package("github.com/gofiber/fiber", "") and
224+
(
225+
// Receiver type: Ctx
226+
receiverName = "Ctx" and
227+
(
228+
// signature: func (*Ctx).JSON(data interface{}) error
229+
methodName = "JSON" and
230+
bodyNode = bodySetterCall.getArgument(0) and
231+
contentTypeString = "application/json"
232+
or
233+
// signature: func (*Ctx).JSONP(data interface{}, callback ...string) error
234+
methodName = "JSONP" and
235+
bodyNode = bodySetterCall.getArgument(0) and
236+
contentTypeString = "application/javascript"
237+
)
238+
)
239+
)
240+
}
241+
242+
/**
243+
* Models HTTP ResponseBody where only the body is set.
244+
*/
245+
private class ResponseBodyNoContentType extends HTTP::ResponseBody::Range {
246+
DataFlow::Node receiverNode;
247+
248+
ResponseBodyNoContentType() {
249+
exists(string package, string receiverName |
250+
setsBody(package, receiverName, receiverNode, this)
251+
)
252+
}
253+
254+
override HTTP::ResponseWriter getResponseWriter() { result.getANode() = receiverNode }
255+
}
256+
257+
// Holds for a call that sets the body. The content-type is not defined.
258+
private predicate setsBody(
259+
string package, string receiverName, DataFlow::Node receiverNode, DataFlow::Node bodyNode
260+
) {
261+
exists(string methodName, Method met, DataFlow::CallNode bodySetterCall |
262+
met.hasQualifiedName(package, receiverName, methodName) and
263+
bodySetterCall = met.getACall() and
264+
receiverNode = bodySetterCall.getReceiver()
265+
|
266+
package = package("github.com/gofiber/fiber", "") and
267+
(
268+
// Receiver type: Ctx
269+
receiverName = "Ctx" and
270+
(
271+
// signature: func (*Ctx).Format(body interface{})
272+
methodName = "Format" and
273+
bodyNode = bodySetterCall.getArgument(0)
274+
or
275+
// signature: func (*Ctx).Send(bodies ...interface{})
276+
methodName = "Send" and
277+
bodyNode = bodySetterCall.getArgument(_)
278+
or
279+
// signature: func (*Ctx).SendBytes(body []byte)
280+
methodName = "SendBytes" and
281+
bodyNode = bodySetterCall.getArgument(0)
282+
or
283+
// signature: func (*Ctx).SendStream(stream io.Reader, size ...int)
284+
methodName = "SendStream" and
285+
bodyNode = bodySetterCall.getArgument(0)
286+
or
287+
// signature: func (*Ctx).SendString(body string)
288+
methodName = "SendString" and
289+
bodyNode = bodySetterCall.getArgument(0)
290+
or
291+
// signature: func (*Ctx).Write(bodies ...interface{})
292+
methodName = "Write" and
293+
bodyNode = bodySetterCall.getArgument(_)
294+
)
295+
)
296+
)
297+
}
298+
299+
/**
300+
* Provides models of untrusted flow sources.
301+
*/
302+
private class UntrustedFlowSources extends UntrustedFlowSource::Range {
303+
UntrustedFlowSources() {
304+
// Methods on types of package: github.com/gofiber/fiber@v1.14.6
305+
exists(string receiverName, string methodName, Method mtd, FunctionOutput out |
306+
this = out.getExitNode(mtd.getACall()) and
307+
mtd.hasQualifiedName(package("github.com/gofiber/fiber", ""), receiverName, methodName)
308+
|
309+
receiverName = "Ctx" and
310+
(
311+
// signature: func (*Ctx).BaseURL() string
312+
methodName = "BaseURL" and
313+
out.isResult()
314+
or
315+
// signature: func (*Ctx).Body() string
316+
methodName = "Body" and
317+
out.isResult()
318+
or
319+
// signature: func (*Ctx).BodyParser(out interface{}) error
320+
methodName = "BodyParser" and
321+
out.isParameter(0)
322+
or
323+
// signature: func (*Ctx).Cookies(key string, defaultValue ...string) string
324+
methodName = "Cookies" and
325+
out.isResult()
326+
or
327+
// signature: func (*Ctx).FormFile(key string) (*mime/multipart.FileHeader, error)
328+
methodName = "FormFile" and
329+
out.isResult(0)
330+
or
331+
// signature: func (*Ctx).FormValue(key string) (value string)
332+
methodName = "FormValue" and
333+
out.isResult()
334+
or
335+
// signature: func (*Ctx).Get(key string, defaultValue ...string) string
336+
methodName = "Get" and
337+
out.isResult()
338+
or
339+
// signature: func (*Ctx).Hostname() string
340+
methodName = "Hostname" and
341+
out.isResult()
342+
or
343+
// signature: func (*Ctx).Method(override ...string) string
344+
methodName = "Method" and
345+
out.isResult()
346+
or
347+
// signature: func (*Ctx).MultipartForm() (*mime/multipart.Form, error)
348+
methodName = "MultipartForm" and
349+
out.isResult(0)
350+
or
351+
// signature: func (*Ctx).OriginalURL() string
352+
methodName = "OriginalURL" and
353+
out.isResult()
354+
or
355+
// signature: func (*Ctx).Params(key string, defaultValue ...string) string
356+
methodName = "Params" and
357+
out.isResult()
358+
or
359+
// signature: func (*Ctx).Path(override ...string) string
360+
methodName = "Path" and
361+
out.isResult()
362+
or
363+
// signature: func (*Ctx).Protocol() string
364+
methodName = "Protocol" and
365+
out.isResult()
366+
or
367+
// signature: func (*Ctx).Query(key string, defaultValue ...string) string
368+
methodName = "Query" and
369+
out.isResult()
370+
or
371+
// signature: func (*Ctx).QueryParser(out interface{}) error
372+
methodName = "QueryParser" and
373+
out.isParameter(0)
374+
or
375+
// signature: func (*Ctx).Range(size int) (rangeData Range, err error)
376+
methodName = "Range" and
377+
out.isResult(0)
378+
or
379+
// signature: func (*Ctx).Subdomains(offset ...int) []string
380+
methodName = "Subdomains" and
381+
out.isResult()
382+
)
383+
)
384+
or
385+
// Structs of package: github.com/gofiber/fiber@v1.14.6
386+
exists(string structName, string fields, DataFlow::Field fld |
387+
this = fld.getARead() and
388+
fld.hasQualifiedName(package("github.com/gofiber/fiber", ""), structName, fields)
389+
|
390+
structName = "Cookie" and
391+
fields = ["Domain", "Name", "Path", "SameSite", "Value"]
392+
or
393+
structName = "Error" and
394+
fields = "Message"
395+
)
396+
}
397+
}
398+
}

ql/test/experimental/frameworks/Fiber/HeaderWrite.expected

Whitespace-only changes.

0 commit comments

Comments
 (0)