Merge pull request #16250 from owen-mc/go/rename-untrusted-flow-source

Go: Rename `UntrustedFlowSource` to `RemoteFlowSource` to match other language libraries
This commit is contained in:
Owen Mansel-Chan
2024-04-24 11:37:00 +01:00
committed by GitHub
75 changed files with 359 additions and 273 deletions

View File

@@ -15,14 +15,14 @@ Sources
------- -------
To mark a source of data that is controlled by an untrusted user, we To mark a source of data that is controlled by an untrusted user, we
create a class extending ``UntrustedFlowSource::Range``. Inheritance and create a class extending ``RemoteFlowSource::Range``. Inheritance and
the characteristic predicate of the class should be used to specify the characteristic predicate of the class should be used to specify
exactly the dataflow node that introduces the data. Here is a short exactly the dataflow node that introduces the data. Here is a short
example from ``Mux.qll``. example from ``Mux.qll``.
.. code-block:: ql .. code-block:: ql
class RequestVars extends DataFlow::UntrustedFlowSource::Range, DataFlow::CallNode { class RequestVars extends DataFlow::RemoteFlowSource::Range, DataFlow::CallNode {
RequestVars() { this.getTarget().hasQualifiedName("github.com/gorilla/mux", "Vars") } RequestVars() { this.getTarget().hasQualifiedName("github.com/gorilla/mux", "Vars") }
} }

View File

@@ -13,14 +13,14 @@ Sources
------- -------
To mark a source of data that is controlled by an untrusted user, we To mark a source of data that is controlled by an untrusted user, we
create a class extending ``UntrustedFlowSource::Range``. Inheritance and create a class extending ``RemoteFlowSource::Range``. Inheritance and
the characteristic predicate of the class should be used to specify the characteristic predicate of the class should be used to specify
exactly the dataflow node that introduces the data. Here is a short exactly the dataflow node that introduces the data. Here is a short
example from ``Mux.qll``. example from ``Mux.qll``.
.. code-block:: ql .. code-block:: ql
class RequestVars extends DataFlow::UntrustedFlowSource::Range, DataFlow::CallNode { class RequestVars extends DataFlow::RemoteFlowSource::Range, DataFlow::CallNode {
RequestVars() { this.getTarget().hasQualifiedName("github.com/gorilla/mux", "Vars") } RequestVars() { this.getTarget().hasQualifiedName("github.com/gorilla/mux", "Vars") }
} }
@@ -119,4 +119,4 @@ Here is a short example from ``Stdlib.qll``, which has been slightly simplified.
This has the effect that any call to ``Print``, ``Printf``, or This has the effect that any call to ``Print``, ``Printf``, or
``Println`` in the package ``fmt`` is recognized as a logger call. ``Println`` in the package ``fmt`` is recognized as a logger call.
Any query that uses logger calls as a sink will then identify when tainted data Any query that uses logger calls as a sink will then identify when tainted data
has been passed as an argument to ``Print``, ``Printf``, or ``Println``. has been passed as an argument to ``Print``, ``Printf``, or ``Println``.

View File

@@ -0,0 +1,5 @@
---
category: deprecated
---
* To make Go consistent with other language libraries, the `UntrustedFlowSource` name has been deprecated throughout. Use `RemoteFlowSource` instead, which replaces it.
* Where modules have classes named `UntrustedFlowAsSource`, these are also deprecated and the `Source` class in the same module or the `RemoteFlowSource` class should be used instead.

View File

@@ -1,12 +1,12 @@
/** /**
* Provides classes for working with untrusted flow sources, sinks and taint propagators * Provides classes for working with remote flow sources, sinks and taint propagators
* from the `github.com/aws/aws-lambda-go/lambda` package. * from the `github.com/aws/aws-lambda-go/lambda` package.
*/ */
import go import go
/** A source of input data in an AWS Lambda. */ /** A source of input data in an AWS Lambda. */
private class LambdaInput extends UntrustedFlowSource::Range { private class LambdaInput extends RemoteFlowSource::Range {
LambdaInput() { LambdaInput() {
exists(Parameter p | p = this.asParameter() | exists(Parameter p | p = this.asParameter() |
p = any(HandlerFunction hf).getAParameter() and p = any(HandlerFunction hf).getAParameter() and

View File

@@ -1,5 +1,5 @@
/** /**
* Provides classes for working with untrusted flow sources, sinks and taint propagators * Provides classes for working with remote flow sources, sinks and taint propagators
* from the `github.com/beego/beego` package. * from the `github.com/beego/beego` package.
*/ */
@@ -9,7 +9,7 @@ private import semmle.go.security.SafeUrlFlowCustomizations
// Some TaintTracking::FunctionModel subclasses remain because varargs functions don't work with Models-as-Data sumamries yet. // Some TaintTracking::FunctionModel subclasses remain because varargs functions don't work with Models-as-Data sumamries yet.
/** /**
* Provides classes for working with untrusted flow sources, sinks and taint propagators * Provides classes for working with remote flow sources, sinks and taint propagators
* from the [Beego](https://github.com/beego/beego) package. * from the [Beego](https://github.com/beego/beego) package.
*/ */
module Beego { module Beego {
@@ -50,7 +50,7 @@ module Beego {
/** /**
* `BeegoInput` sources of untrusted data. * `BeegoInput` sources of untrusted data.
*/ */
private class BeegoInputSource extends UntrustedFlowSource::Range { private class BeegoInputSource extends RemoteFlowSource::Range {
string methodName; string methodName;
BeegoInputSource() { BeegoInputSource() {
@@ -81,7 +81,7 @@ module Beego {
/** /**
* `beego.Controller` sources of untrusted data. * `beego.Controller` sources of untrusted data.
*/ */
private class BeegoControllerSource extends UntrustedFlowSource::Range { private class BeegoControllerSource extends RemoteFlowSource::Range {
BeegoControllerSource() { BeegoControllerSource() {
exists(string methodName, FunctionOutput output | exists(string methodName, FunctionOutput output |
methodName = "ParseForm" and methodName = "ParseForm" and
@@ -105,7 +105,7 @@ module Beego {
/** /**
* `BeegoInputRequestBody` sources of untrusted data. * `BeegoInputRequestBody` sources of untrusted data.
*/ */
private class BeegoInputRequestBodySource extends UntrustedFlowSource::Range { private class BeegoInputRequestBodySource extends RemoteFlowSource::Range {
BeegoInputRequestBodySource() { BeegoInputRequestBodySource() {
exists(DataFlow::FieldReadNode frn | this = frn | exists(DataFlow::FieldReadNode frn | this = frn |
frn.getField().hasQualifiedName(contextPackagePath(), "BeegoInput", "RequestBody") frn.getField().hasQualifiedName(contextPackagePath(), "BeegoInput", "RequestBody")
@@ -116,7 +116,7 @@ module Beego {
/** /**
* `beego/context.Context` sources of untrusted data. * `beego/context.Context` sources of untrusted data.
*/ */
private class BeegoContextSource extends UntrustedFlowSource::Range { private class BeegoContextSource extends RemoteFlowSource::Range {
BeegoContextSource() { BeegoContextSource() {
exists(Method m | m.hasQualifiedName(contextPackagePath(), "Context", "GetCookie") | exists(Method m | m.hasQualifiedName(contextPackagePath(), "Context", "GetCookie") |
this = m.getACall().getResult() this = m.getACall().getResult()

View File

@@ -1,5 +1,5 @@
/** /**
* Provides classes for working with untrusted flow sources, sinks and taint propagators * Provides classes for working with remote flow sources, sinks and taint propagators
* from the `github.com/astaxie/beego/orm` subpackage. * from the `github.com/astaxie/beego/orm` subpackage.
*/ */
@@ -7,7 +7,7 @@ import go
private import semmle.go.security.StoredXssCustomizations private import semmle.go.security.StoredXssCustomizations
/** /**
* Provides classes for working with untrusted flow sources, sinks and taint propagators * Provides classes for working with remote flow sources, sinks and taint propagators
* from the [Beego ORM](https://github.com/astaxie/beego/orm) subpackage. * from the [Beego ORM](https://github.com/astaxie/beego/orm) subpackage.
*/ */
module BeegoOrm { module BeegoOrm {

View File

@@ -1,5 +1,5 @@
/** /**
* Provides classes for working with untrusted flow sources from the `github.com/go-chi/chi` package. * Provides classes for working with remote flow sources from the `github.com/go-chi/chi` package.
*/ */
import go import go
@@ -9,18 +9,18 @@ private module Chi {
string packagePath() { result = package("github.com/go-chi/chi", "") } string packagePath() { result = package("github.com/go-chi/chi", "") }
/** /**
* Functions that extract URL parameters, considered as a source of untrusted flow. * Functions that extract URL parameters, considered as a source of remote flow.
*/ */
private class UserControlledFunction extends UntrustedFlowSource::Range, DataFlow::CallNode { private class UserControlledFunction extends RemoteFlowSource::Range, DataFlow::CallNode {
UserControlledFunction() { UserControlledFunction() {
this.getTarget().hasQualifiedName(packagePath(), ["URLParam", "URLParamFromCtx"]) this.getTarget().hasQualifiedName(packagePath(), ["URLParam", "URLParamFromCtx"])
} }
} }
/** /**
* Methods that extract URL parameters, considered as a source of untrusted flow. * Methods that extract URL parameters, considered as a source of remote flow.
*/ */
private class UserControlledRequestMethod extends UntrustedFlowSource::Range, private class UserControlledRequestMethod extends RemoteFlowSource::Range,
DataFlow::MethodCallNode DataFlow::MethodCallNode
{ {
UserControlledRequestMethod() { UserControlledRequestMethod() {

View File

@@ -1,5 +1,5 @@
/** /**
* Provides classes for working with untrusted flow sources, taint propagators, and HTTP sinks * Provides classes for working with remote flow sources, taint propagators, and HTTP sinks
* from the `github.com/labstack/echo` package. * from the `github.com/labstack/echo` package.
*/ */
@@ -10,9 +10,9 @@ private module Echo {
private string packagePath() { result = package("github.com/labstack/echo", "") } private string packagePath() { result = package("github.com/labstack/echo", "") }
/** /**
* Data from a `Context` interface method, considered as a source of untrusted flow. * Data from a `Context` interface method, considered as a source of remote flow.
*/ */
private class EchoContextSource extends UntrustedFlowSource::Range { private class EchoContextSource extends RemoteFlowSource::Range {
EchoContextSource() { EchoContextSource() {
exists(DataFlow::MethodCallNode call, string methodName | exists(DataFlow::MethodCallNode call, string methodName |
methodName = methodName =
@@ -42,7 +42,7 @@ private module Echo {
/** /**
* A call to a method on `Context` struct that unmarshals data into a target. * A call to a method on `Context` struct that unmarshals data into a target.
*/ */
private class EchoContextBinder extends UntrustedFlowSource::Range { private class EchoContextBinder extends RemoteFlowSource::Range {
EchoContextBinder() { EchoContextBinder() {
exists(DataFlow::MethodCallNode call | exists(DataFlow::MethodCallNode call |
call.getTarget().hasQualifiedName(packagePath(), "Context", "Bind") call.getTarget().hasQualifiedName(packagePath(), "Context", "Bind")

View File

@@ -95,7 +95,7 @@ module ElazarlGoproxy {
} }
} }
private class UserControlledRequestData extends UntrustedFlowSource::Range { private class UserControlledRequestData extends RemoteFlowSource::Range {
UserControlledRequestData() { UserControlledRequestData() {
exists(DataFlow::FieldReadNode frn | this = frn | exists(DataFlow::FieldReadNode frn | this = frn |
// liberally consider ProxyCtx.UserData to be untrusted; it's a data field set by a request handler // liberally consider ProxyCtx.UserData to be untrusted; it's a data field set by a request handler

View File

@@ -1,5 +1,5 @@
/** /**
* Provides classes for working with untrusted flow sources, sinks and taint propagators * Provides classes for working with remote flow sources, sinks and taint propagators
* from the `github.com/valyala/fasthttp` package. * from the `github.com/valyala/fasthttp` package.
*/ */
@@ -255,11 +255,16 @@ module Fasthttp {
* Provide modeling for fasthttp.URI Type. * Provide modeling for fasthttp.URI Type.
*/ */
module URI { module URI {
/**
* DEPRECATED: Use `RemoteFlowSource` instead.
*/
deprecated class UntrustedFlowSource = RemoteFlowSource;
/** /**
* The methods as Remote user controllable source which are part of the incoming URL. * The methods as Remote user controllable source which are part of the incoming URL.
*/ */
class UntrustedFlowSource extends UntrustedFlowSource::Range instanceof DataFlow::Node { class RemoteFlowSource extends RemoteFlowSource::Range instanceof DataFlow::Node {
UntrustedFlowSource() { RemoteFlowSource() {
exists(Method m | exists(Method m |
m.hasQualifiedName(packagePath(), "URI", m.hasQualifiedName(packagePath(), "URI",
["FullURI", "LastPathSegment", "Path", "PathOriginal", "QueryString", "String"]) and ["FullURI", "LastPathSegment", "Path", "PathOriginal", "QueryString", "String"]) and
@@ -273,13 +278,18 @@ module Fasthttp {
* Provide modeling for fasthttp.Args Type. * Provide modeling for fasthttp.Args Type.
*/ */
module Args { module Args {
/**
* DEPRECATED: Use `RemoteFlowSource` instead.
*/
deprecated class UntrustedFlowSource = RemoteFlowSource;
/** /**
* The methods as Remote user controllable source which are part of the incoming URL Parameters. * The methods as Remote user controllable source which are part of the incoming URL Parameters.
* *
* When support for lambdas has been implemented we should model "VisitAll". * When support for lambdas has been implemented we should model "VisitAll".
*/ */
class UntrustedFlowSource extends UntrustedFlowSource::Range instanceof DataFlow::Node { class RemoteFlowSource extends RemoteFlowSource::Range instanceof DataFlow::Node {
UntrustedFlowSource() { RemoteFlowSource() {
exists(Method m | exists(Method m |
m.hasQualifiedName(packagePath(), "Args", m.hasQualifiedName(packagePath(), "Args",
["Peek", "PeekBytes", "PeekMulti", "PeekMultiBytes", "QueryString", "String"]) and ["Peek", "PeekBytes", "PeekMulti", "PeekMultiBytes", "QueryString", "String"]) and
@@ -386,11 +396,16 @@ module Fasthttp {
* Provide modeling for fasthttp.Request Type. * Provide modeling for fasthttp.Request Type.
*/ */
module Request { module Request {
/**
* DEPRECATED: Use `RemoteFlowSource` instead.
*/
deprecated class UntrustedFlowSource = RemoteFlowSource;
/** /**
* The methods as Remote user controllable source which can be many part of request. * The methods as Remote user controllable source which can be many part of request.
*/ */
class UntrustedFlowSource extends UntrustedFlowSource::Range instanceof DataFlow::Node { class RemoteFlowSource extends RemoteFlowSource::Range instanceof DataFlow::Node {
UntrustedFlowSource() { RemoteFlowSource() {
exists(Method m | exists(Method m |
m.hasQualifiedName(packagePath(), "Request", m.hasQualifiedName(packagePath(), "Request",
[ [
@@ -463,13 +478,18 @@ module Fasthttp {
override Http::ResponseWriter getResponseWriter() { none() } override Http::ResponseWriter getResponseWriter() { none() }
} }
/**
* DEPRECATED: Use `RemoteFlowSource` instead.
*/
deprecated class UntrustedFlowSource = RemoteFlowSource;
/** /**
* The methods as Remote user controllable source which are generally related to HTTP request. * The methods as Remote user controllable source which are generally related to HTTP request.
* *
* When support for lambdas has been implemented we should model "VisitAll", "VisitAllCookie", "VisitAllInOrder", "VisitAllTrailer". * When support for lambdas has been implemented we should model "VisitAll", "VisitAllCookie", "VisitAllInOrder", "VisitAllTrailer".
*/ */
class UntrustedFlowSource extends UntrustedFlowSource::Range instanceof DataFlow::Node { class RemoteFlowSource extends RemoteFlowSource::Range instanceof DataFlow::Node {
UntrustedFlowSource() { RemoteFlowSource() {
exists(Method m | exists(Method m |
m.hasQualifiedName(packagePath(), "RequestCtx", m.hasQualifiedName(packagePath(), "RequestCtx",
[ [
@@ -486,13 +506,18 @@ module Fasthttp {
* Provide Methods of fasthttp.RequestHeader which mostly used as remote user controlled sources. * Provide Methods of fasthttp.RequestHeader which mostly used as remote user controlled sources.
*/ */
module RequestHeader { module RequestHeader {
/**
* DEPRECATED: Use `RemoteFlowSource` instead.
*/
deprecated class UntrustedFlowSource = RemoteFlowSource;
/** /**
* The methods as Remote user controllable source which are mostly related to HTTP Request Headers. * The methods as Remote user controllable source which are mostly related to HTTP Request Headers.
* *
* When support for lambdas has been implemented we should model "VisitAll", "VisitAllCookie", "VisitAllInOrder", "VisitAllTrailer". * When support for lambdas has been implemented we should model "VisitAll", "VisitAllCookie", "VisitAllInOrder", "VisitAllTrailer".
*/ */
class UntrustedFlowSource extends UntrustedFlowSource::Range instanceof DataFlow::Node { class RemoteFlowSource extends RemoteFlowSource::Range instanceof DataFlow::Node {
UntrustedFlowSource() { RemoteFlowSource() {
exists(Method m | exists(Method m |
m.hasQualifiedName(packagePath(), "RequestHeader", m.hasQualifiedName(packagePath(), "RequestHeader",
[ [

View File

@@ -10,9 +10,9 @@ private module Gin {
string packagePath() { result = package("github.com/gin-gonic/gin", "") } string packagePath() { result = package("github.com/gin-gonic/gin", "") }
/** /**
* Data from a `Context` struct, considered as a source of untrusted flow. * Data from a `Context` struct, considered as a source of remote flow.
*/ */
private class GithubComGinGonicGinContextSource extends UntrustedFlowSource::Range { private class GithubComGinGonicGinContextSource extends RemoteFlowSource::Range {
GithubComGinGonicGinContextSource() { GithubComGinGonicGinContextSource() {
// Method calls: // Method calls:
exists(DataFlow::MethodCallNode call, string methodName | exists(DataFlow::MethodCallNode call, string methodName |
@@ -39,7 +39,7 @@ private module Gin {
/** /**
* A call to a method on `Context` struct that unmarshals data into a target. * A call to a method on `Context` struct that unmarshals data into a target.
*/ */
private class GithubComGinGonicGinContextBindSource extends UntrustedFlowSource::Range { private class GithubComGinGonicGinContextBindSource extends RemoteFlowSource::Range {
GithubComGinGonicGinContextBindSource() { GithubComGinGonicGinContextBindSource() {
exists(DataFlow::MethodCallNode call, string methodName | exists(DataFlow::MethodCallNode call, string methodName |
call.getTarget().hasQualifiedName(packagePath(), "Context", methodName) and call.getTarget().hasQualifiedName(packagePath(), "Context", methodName) and

View File

@@ -35,7 +35,7 @@ module GoKit {
DataFlow::exprNode(result.(FuncLit)) = getAnEndpointFactoryResult() DataFlow::exprNode(result.(FuncLit)) = getAnEndpointFactoryResult()
} }
private class EndpointRequest extends UntrustedFlowSource::Range { private class EndpointRequest extends RemoteFlowSource::Range {
EndpointRequest() { this = DataFlow::parameterNode(getAnEndpointFunction().getParameter(1)) } EndpointRequest() { this = DataFlow::parameterNode(getAnEndpointFunction().getParameter(1)) }
} }
} }

View File

@@ -142,7 +142,7 @@ module GoMicro {
/** /**
* A set of remote requests from a service handler. * A set of remote requests from a service handler.
*/ */
class Request extends UntrustedFlowSource::Range instanceof DataFlow::ParameterNode { class Request extends RemoteFlowSource::Range instanceof DataFlow::ParameterNode {
Request() { Request() {
exists(ServiceHandler handler | exists(ServiceHandler handler |
this.asParameter().isParameterOf(handler.getFuncDecl(), 1) and this.asParameter().isParameterOf(handler.getFuncDecl(), 1) and

View File

@@ -27,14 +27,14 @@ private module GoRestfulHttp {
/** /**
* A model of go-restful's `Request` object as a source of user-controlled data. * A model of go-restful's `Request` object as a source of user-controlled data.
*/ */
private class GoRestfulSource extends UntrustedFlowSource::Range { private class GoRestfulSource extends RemoteFlowSource::Range {
GoRestfulSource() { this = any(GoRestfulSourceMethod g).getACall() } GoRestfulSource() { this = any(GoRestfulSourceMethod g).getACall() }
} }
/** /**
* A model of go-restful's `Request.ReadEntity` method as a source of user-controlled data. * A model of go-restful's `Request.ReadEntity` method as a source of user-controlled data.
*/ */
private class GoRestfulReadEntitySource extends UntrustedFlowSource::Range { private class GoRestfulReadEntitySource extends RemoteFlowSource::Range {
GoRestfulReadEntitySource() { GoRestfulReadEntitySource() {
exists(DataFlow::MethodCallNode call | exists(DataFlow::MethodCallNode call |
call.getTarget().hasQualifiedName(packagePath(), "Request", "ReadEntity") call.getTarget().hasQualifiedName(packagePath(), "Request", "ReadEntity")

View File

@@ -39,7 +39,7 @@ module Gqlgen {
} }
/** A parameter of a resolver method which receives untrusted input. */ /** A parameter of a resolver method which receives untrusted input. */
class ResolverParameter extends UntrustedFlowSource::Range instanceof DataFlow::ParameterNode { class ResolverParameter extends RemoteFlowSource::Range instanceof DataFlow::ParameterNode {
ResolverParameter() { ResolverParameter() {
this.asParameter() = any(ResolverImplementationMethod h).getAnUntrustedParameter() this.asParameter() = any(ResolverImplementationMethod h).getAnUntrustedParameter()
} }

View File

@@ -9,7 +9,7 @@ import go
*/ */
module Mux { module Mux {
/** An access to a Mux middleware variable. */ /** An access to a Mux middleware variable. */
class RequestVars extends DataFlow::UntrustedFlowSource::Range, DataFlow::CallNode { class RequestVars extends DataFlow::RemoteFlowSource::Range, DataFlow::CallNode {
RequestVars() { RequestVars() {
this.getTarget().hasQualifiedName(package("github.com/gorilla/mux", ""), "Vars") this.getTarget().hasQualifiedName(package("github.com/gorilla/mux", ""), "Vars")
} }

View File

@@ -1,5 +1,5 @@
/** /**
* Provides classes for working with untrusted flow sources from the `github.com/revel/revel` package. * Provides classes for working with remote flow sources from the `github.com/revel/revel` package.
*/ */
import go import go
@@ -12,7 +12,7 @@ module Revel {
result = package(["github.com/revel", "github.com/robfig"] + "/revel", "") result = package(["github.com/revel", "github.com/robfig"] + "/revel", "")
} }
private class ControllerParams extends UntrustedFlowSource::Range, DataFlow::FieldReadNode { private class ControllerParams extends RemoteFlowSource::Range, DataFlow::FieldReadNode {
ControllerParams() { ControllerParams() {
exists(Field f | exists(Field f |
this.readsField(_, f) and this.readsField(_, f) and
@@ -32,7 +32,7 @@ module Revel {
} }
} }
private class RouteMatchParams extends UntrustedFlowSource::Range, DataFlow::FieldReadNode { private class RouteMatchParams extends RemoteFlowSource::Range, DataFlow::FieldReadNode {
RouteMatchParams() { RouteMatchParams() {
exists(Field f | exists(Field f |
this.readsField(_, f) and this.readsField(_, f) and
@@ -42,9 +42,7 @@ module Revel {
} }
/** An access to an HTTP request field whose value may be controlled by an untrusted user. */ /** An access to an HTTP request field whose value may be controlled by an untrusted user. */
private class UserControlledRequestField extends UntrustedFlowSource::Range, private class UserControlledRequestField extends RemoteFlowSource::Range, DataFlow::FieldReadNode {
DataFlow::FieldReadNode
{
UserControlledRequestField() { UserControlledRequestField() {
exists(string fieldName | exists(string fieldName |
this.getField().hasQualifiedName(packagePath(), "Request", fieldName) this.getField().hasQualifiedName(packagePath(), "Request", fieldName)
@@ -56,7 +54,7 @@ module Revel {
} }
} }
private class UserControlledRequestMethod extends UntrustedFlowSource::Range, private class UserControlledRequestMethod extends RemoteFlowSource::Range,
DataFlow::MethodCallNode DataFlow::MethodCallNode
{ {
UserControlledRequestMethod() { UserControlledRequestMethod() {

View File

@@ -130,7 +130,7 @@ module Twirp {
} }
/** A request coming to the service handler. */ /** A request coming to the service handler. */
class Request extends UntrustedFlowSource::Range instanceof DataFlow::ParameterNode { class Request extends RemoteFlowSource::Range instanceof DataFlow::ParameterNode {
Request() { Request() {
exists(ServiceHandler handler | exists(ServiceHandler handler |
this.asParameter().isParameterOf(handler.getFuncDecl(), 1) and this.asParameter().isParameterOf(handler.getFuncDecl(), 1) and

View File

@@ -127,7 +127,7 @@ module WebSocketRequestCall {
/** /**
* A message written to a WebSocket, considered as a flow sink for reflected XSS. * A message written to a WebSocket, considered as a flow sink for reflected XSS.
*/ */
class WebSocketReaderAsSource extends UntrustedFlowSource::Range { class WebSocketReaderAsSource extends RemoteFlowSource::Range {
WebSocketReaderAsSource() { WebSocketReaderAsSource() {
exists(WebSocketReader r | this = r.getAnOutput().getNode(r.getACall())) exists(WebSocketReader r | this = r.getAnOutput().getNode(r.getACall()))
} }

View File

@@ -9,9 +9,7 @@ private import semmle.go.dataflow.internal.FlowSummaryImpl::Private
/** Provides models of commonly used functions in the `net/http` package. */ /** Provides models of commonly used functions in the `net/http` package. */
module NetHttp { module NetHttp {
/** An access to an HTTP request field whose value may be controlled by an untrusted user. */ /** An access to an HTTP request field whose value may be controlled by an untrusted user. */
private class UserControlledRequestField extends UntrustedFlowSource::Range, private class UserControlledRequestField extends RemoteFlowSource::Range, DataFlow::FieldReadNode {
DataFlow::FieldReadNode
{
UserControlledRequestField() { UserControlledRequestField() {
exists(string fieldName | this.getField().hasQualifiedName("net/http", "Request", fieldName) | exists(string fieldName | this.getField().hasQualifiedName("net/http", "Request", fieldName) |
fieldName = fieldName =

View File

@@ -29,8 +29,13 @@ module CommandInjection {
*/ */
abstract class Sanitizer extends DataFlow::Node { } abstract class Sanitizer extends DataFlow::Node { }
/**
* DEPRECATED: Use `RemoteFlowSource` or `Source` instead.
*/
deprecated class UntrustedFlowAsSource = RemoteFlowAsSource;
/** A source of untrusted data, considered as a taint source for command injection. */ /** A source of untrusted data, considered as a taint source for command injection. */
class UntrustedFlowAsSource extends Source instanceof UntrustedFlowSource { } private class RemoteFlowAsSource extends Source instanceof RemoteFlowSource { }
/** A command name, considered as a taint sink for command injection. */ /** A command name, considered as a taint sink for command injection. */
class CommandNameAsSink extends Sink { class CommandNameAsSink extends Sink {

View File

@@ -187,13 +187,13 @@ class UnknownExternalApiDataNode extends ExternalApiDataNode {
deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration { deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfig" } UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
} }
private module UntrustedDataConfig implements DataFlow::ConfigSig { private module UntrustedDataConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource } predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
} }
@@ -211,13 +211,13 @@ module UntrustedDataToExternalApiFlow = DataFlow::Global<UntrustedDataConfig>;
deprecated class UntrustedDataToUnknownExternalApiConfig extends TaintTracking::Configuration { deprecated class UntrustedDataToUnknownExternalApiConfig extends TaintTracking::Configuration {
UntrustedDataToUnknownExternalApiConfig() { this = "UntrustedDataToUnknownExternalAPIConfig" } UntrustedDataToUnknownExternalApiConfig() { this = "UntrustedDataToUnknownExternalAPIConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof UnknownExternalApiDataNode } override predicate isSink(DataFlow::Node sink) { sink instanceof UnknownExternalApiDataNode }
} }
private module UntrustedDataToUnknownExternalApiConfig implements DataFlow::ConfigSig { private module UntrustedDataToUnknownExternalApiConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource } predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof UnknownExternalApiDataNode } predicate isSink(DataFlow::Node sink) { sink instanceof UnknownExternalApiDataNode }
} }

View File

@@ -5,21 +5,31 @@
import go import go
private import semmle.go.dataflow.ExternalFlow as ExternalFlow private import semmle.go.dataflow.ExternalFlow as ExternalFlow
/**
* DEPRECATED: Use `RemoteFlowSource` instead.
*/
deprecated class UntrustedFlowSource = RemoteFlowSource;
/** /**
* A source of data that is controlled by an untrusted user. * A source of data that is controlled by an untrusted user.
* *
* Extend this class to refine existing API models. If you want to model new APIs, * Extend this class to refine existing API models. If you want to model new APIs,
* extend `UntrustedFlowSource::Range` instead. * extend `RemoteFlowSource::Range` instead.
*/ */
class UntrustedFlowSource extends DataFlow::Node instanceof UntrustedFlowSource::Range { } class RemoteFlowSource extends DataFlow::Node instanceof RemoteFlowSource::Range { }
/**
* DEPRECATED: Use `RemoteFlowSource` instead.
*/
deprecated module UntrustedFlowSource = RemoteFlowSource;
/** Provides a class for modeling new sources of untrusted data. */ /** Provides a class for modeling new sources of untrusted data. */
module UntrustedFlowSource { module RemoteFlowSource {
/** /**
* A source of data that is controlled by an untrusted user. * A source of data that is controlled by an untrusted user.
* *
* Extend this class to model new APIs. If you want to refine existing API models, * Extend this class to model new APIs. If you want to refine existing API models,
* extend `UntrustedFlowSource` instead. * extend `RemoteFlowSource` instead.
*/ */
abstract class Range extends DataFlow::Node { } abstract class Range extends DataFlow::Node { }

View File

@@ -25,8 +25,13 @@ module LogInjection {
*/ */
abstract class Sanitizer extends DataFlow::Node { } abstract class Sanitizer extends DataFlow::Node { }
/**
* DEPRECATED: Use `RemoteFlowSource` or `Source` instead.
*/
deprecated class UntrustedFlowAsSource = RemoteFlowAsSource;
/** A source of untrusted data, considered as a taint source for log injection. */ /** A source of untrusted data, considered as a taint source for log injection. */
class UntrustedFlowAsSource extends Source instanceof UntrustedFlowSource { } private class RemoteFlowAsSource extends Source instanceof RemoteFlowSource { }
/** An argument to a logging mechanism. */ /** An argument to a logging mechanism. */
class LoggerSink extends Sink { class LoggerSink extends Sink {

View File

@@ -49,7 +49,7 @@ module MissingJwtSignatureCheck {
} }
} }
private class DefaultSource extends Source instanceof UntrustedFlowSource { } private class DefaultSource extends Source instanceof RemoteFlowSource { }
private class DefaultSink extends Sink { private class DefaultSink extends Sink {
DefaultSink() { sinkNode(this, "jwt") } DefaultSink() { sinkNode(this, "jwt") }

View File

@@ -42,11 +42,16 @@ module OpenUrlRedirect {
abstract predicate hasTaintStep(DataFlow::Node pred, DataFlow::Node succ); abstract predicate hasTaintStep(DataFlow::Node pred, DataFlow::Node succ);
} }
/**
* DEPRECATED: Use `RemoteFlowSource` or `Source` instead.
*/
deprecated class UntrustedFlowAsSource = RemoteFlowAsSource;
/** /**
* A source of third-party user input, considered as a flow source for URL redirects. * A source of third-party user input, considered as a flow source for URL redirects.
*/ */
class UntrustedFlowAsSource extends Source, UntrustedFlowSource { private class RemoteFlowAsSource extends Source instanceof RemoteFlowSource {
UntrustedFlowAsSource() { RemoteFlowAsSource() {
// exclude some fields and methods of URLs that are generally not attacker-controllable for // exclude some fields and methods of URLs that are generally not attacker-controllable for
// open redirect exploits // open redirect exploits
not this instanceof Http::Redirect::UnexploitableSource not this instanceof Http::Redirect::UnexploitableSource

View File

@@ -34,10 +34,15 @@ module ReflectedXss {
} }
} }
/**
* DEPRECATED: Use `RemoteFlowSource` or `Source` instead.
*/
deprecated class UntrustedFlowAsSource = RemoteFlowAsSource;
/** /**
* A third-party controllable input, considered as a flow source for reflected XSS. * A third-party controllable input, considered as a flow source for reflected XSS.
*/ */
class UntrustedFlowAsSource extends Source, UntrustedFlowSource { } private class RemoteFlowAsSource extends Source instanceof RemoteFlowSource { }
/** An arbitrary XSS sink, considered as a flow sink for stored XSS. */ /** An arbitrary XSS sink, considered as a flow sink for stored XSS. */
private class AnySink extends Sink instanceof SharedXss::Sink { } private class AnySink extends Sink instanceof SharedXss::Sink { }

View File

@@ -32,10 +32,15 @@ module RequestForgery {
/** An outgoing sanitizer edge for request forgery vulnerabilities. */ /** An outgoing sanitizer edge for request forgery vulnerabilities. */
abstract class SanitizerEdge extends DataFlow::Node { } abstract class SanitizerEdge extends DataFlow::Node { }
/**
* DEPRECATED: Use `RemoteFlowSource` or `Source` instead.
*/
deprecated class UntrustedFlowAsSource = RemoteFlowAsSource;
/** /**
* A third-party controllable input, considered as a flow source for request forgery. * A third-party controllable input, considered as a flow source for request forgery.
*/ */
class UntrustedFlowAsSource extends Source, UntrustedFlowSource { } private class RemoteFlowAsSource extends Source instanceof RemoteFlowSource { }
/** /**
* The URL of an HTTP request, viewed as a sink for request forgery. * The URL of an HTTP request, viewed as a sink for request forgery.

View File

@@ -25,8 +25,13 @@ module SqlInjection {
*/ */
abstract class Sanitizer extends DataFlow::Node { } abstract class Sanitizer extends DataFlow::Node { }
/**
* DEPRECATED: Use `RemoteFlowSource` or `Source` instead.
*/
deprecated class UntrustedFlowAsSource = RemoteFlowAsSource;
/** A source of untrusted data, considered as a taint source for SQL injection. */ /** A source of untrusted data, considered as a taint source for SQL injection. */
class UntrustedFlowAsSource extends Source instanceof UntrustedFlowSource { } private class RemoteFlowAsSource extends Source instanceof RemoteFlowSource { }
/** An SQL string, considered as a taint sink for SQL injection. */ /** An SQL string, considered as a taint sink for SQL injection. */
class SqlQueryAsSink extends Sink instanceof SQL::QueryString { } class SqlQueryAsSink extends Sink instanceof SQL::QueryString { }

View File

@@ -44,8 +44,13 @@ module TaintedPath {
} }
} }
/**
* DEPRECATED: Use `RemoteFlowSource` or `Source` instead.
*/
deprecated class UntrustedFlowAsSource = RemoteFlowAsSource;
/** A source of untrusted data, considered as a taint source for path traversal. */ /** A source of untrusted data, considered as a taint source for path traversal. */
class UntrustedFlowAsSource extends Source instanceof UntrustedFlowSource { } private class RemoteFlowAsSource extends Source instanceof RemoteFlowSource { }
/** A path expression, considered as a taint sink for path traversal. */ /** A path expression, considered as a taint sink for path traversal. */
class PathAsSink extends Sink { class PathAsSink extends Sink {

View File

@@ -21,7 +21,7 @@ module UncontrolledAllocationSize {
abstract class Sanitizer extends DataFlow::Node { } abstract class Sanitizer extends DataFlow::Node { }
/** A source of untrusted data, considered as a taint source for uncontrolled size allocation vulnerabilities. */ /** A source of untrusted data, considered as a taint source for uncontrolled size allocation vulnerabilities. */
private class UntrustedFlowAsSource extends Source instanceof UntrustedFlowSource { } private class RemoteFlowAsSource extends Source instanceof RemoteFlowSource { }
/** The size argument of a memory allocation function. */ /** The size argument of a memory allocation function. */
private class AllocationSizeAsSink extends Sink instanceof AllocationSizeOverflow::AllocationSize { private class AllocationSizeAsSink extends Sink instanceof AllocationSizeOverflow::AllocationSize {

View File

@@ -24,8 +24,13 @@ module XPathInjection {
*/ */
abstract class Sanitizer extends DataFlow::ExprNode { } abstract class Sanitizer extends DataFlow::ExprNode { }
/**
* DEPRECATED: Use `RemoteFlowSource` or `Source` instead.
*/
deprecated class UntrustedFlowAsSource = RemoteFlowAsSource;
/** A source of untrusted data, used in an XPath expression. */ /** A source of untrusted data, used in an XPath expression. */
class UntrustedFlowAsSource extends Source instanceof UntrustedFlowSource { } private class RemoteFlowAsSource extends Source instanceof RemoteFlowSource { }
/** An XPath expression string, considered as a taint sink for XPath injection. */ /** An XPath expression string, considered as a taint sink for XPath injection. */
class XPathExpressionStringAsSink extends Sink instanceof XPath::XPathExpressionString { } class XPathExpressionStringAsSink extends Sink instanceof XPath::XPathExpressionString { }

View File

@@ -16,8 +16,13 @@ module EmailInjection {
*/ */
abstract class Sink extends DataFlow::Node { } abstract class Sink extends DataFlow::Node { }
/**
* DEPRECATED: Use `RemoteFlowSource` or `Source` instead.
*/
deprecated class UntrustedFlowSourceAsSource = RemoteFlowSourceAsSource;
/** A source of untrusted data, considered as a taint source for email injection. */ /** A source of untrusted data, considered as a taint source for email injection. */
class UntrustedFlowSourceAsSource extends Source instanceof UntrustedFlowSource { } private class RemoteFlowSourceAsSource extends Source instanceof RemoteFlowSource { }
/** /**
* A data-flow node that becomes part of an email considered as a taint sink for email injection. * A data-flow node that becomes part of an email considered as a taint sink for email injection.

View File

@@ -98,13 +98,13 @@ private class LdapClientDNSink extends LdapSink {
/** /**
* DEPRECATED: Use `LdapInjectionFlow` instead. * DEPRECATED: Use `LdapInjectionFlow` instead.
* *
* A taint-tracking configuration for reasoning about when an `UntrustedFlowSource` * A taint-tracking configuration for reasoning about when a `RemoteFlowSource`
* flows into an argument or field that is vulnerable to LDAP injection. * flows into an argument or field that is vulnerable to LDAP injection.
*/ */
deprecated class LdapInjectionConfiguration extends TaintTracking::Configuration { deprecated class LdapInjectionConfiguration extends TaintTracking::Configuration {
LdapInjectionConfiguration() { this = "Ldap injection" } LdapInjectionConfiguration() { this = "Ldap injection" }
override predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof LdapSink } override predicate isSink(DataFlow::Node sink) { sink instanceof LdapSink }
@@ -112,7 +112,7 @@ deprecated class LdapInjectionConfiguration extends TaintTracking::Configuration
} }
private module LdapInjectionConfig implements DataFlow::ConfigSig { private module LdapInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource } predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof LdapSink } predicate isSink(DataFlow::Node sink) { sink instanceof LdapSink }
@@ -120,7 +120,7 @@ private module LdapInjectionConfig implements DataFlow::ConfigSig {
} }
/** /**
* Tracks taint flow for reasoning about when an `UntrustedFlowSource` flows * Tracks taint flow for reasoning about when a `RemoteFlowSource` flows
* into an argument or field that is vulnerable to LDAP injection. * into an argument or field that is vulnerable to LDAP injection.
*/ */
module LdapInjectionFlow = TaintTracking::Global<LdapInjectionConfig>; module LdapInjectionFlow = TaintTracking::Global<LdapInjectionConfig>;

View File

@@ -98,7 +98,7 @@ private class SensitiveStringSink extends Sink {
module Config implements DataFlow::ConfigSig { module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { predicate isSource(DataFlow::Node source) {
source instanceof UntrustedFlowSource and not isBadResult(source) source instanceof RemoteFlowSource and not isBadResult(source)
} }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink and not isBadResult(sink) } predicate isSink(DataFlow::Node sink) { sink instanceof Sink and not isBadResult(sink) }

View File

@@ -68,7 +68,7 @@ module ImproperLdapAuth {
private module Config implements DataFlow::ConfigSig { private module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { predicate isSource(DataFlow::Node source) {
source instanceof UntrustedFlowSource or source instanceof EmptyString source instanceof RemoteFlowSource or source instanceof EmptyString
} }
predicate isSink(DataFlow::Node sink) { sink instanceof LdapAuthSink } predicate isSink(DataFlow::Node sink) { sink instanceof LdapAuthSink }

View File

@@ -28,7 +28,7 @@ predicate divideByZeroSanitizerGuard(DataFlow::Node g, Expr e, boolean branch) {
} }
module Config implements DataFlow::ConfigSig { module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource } predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(Function f, DataFlow::CallNode cn | cn = f.getACall() | exists(Function f, DataFlow::CallNode cn | cn = f.getACall() |

View File

@@ -13,8 +13,8 @@ import go
import DsnInjectionCustomizations import DsnInjectionCustomizations
import DsnInjectionFlow::PathGraph import DsnInjectionFlow::PathGraph
/** An untrusted flow source taken as a source for the `DsnInjection` taint-flow configuration. */ /** A remote flow source taken as a source for the `DsnInjection` taint-flow configuration. */
private class UntrustedFlowAsSource extends Source instanceof UntrustedFlowSource { } private class RemoteFlowAsSource extends Source instanceof RemoteFlowSource { }
from DsnInjectionFlow::PathNode source, DsnInjectionFlow::PathNode sink from DsnInjectionFlow::PathNode source, DsnInjectionFlow::PathNode sink
where DsnInjectionFlow::flowPath(source, sink) where DsnInjectionFlow::flowPath(source, sink)

View File

@@ -36,7 +36,7 @@ class PassthroughTypeName extends string {
} }
module UntrustedToPassthroughTypeConversionConfig implements DataFlow::ConfigSig { module UntrustedToPassthroughTypeConversionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource } predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
additional predicate isSinkToPassthroughType(DataFlow::TypeCastNode sink, PassthroughTypeName name) { additional predicate isSinkToPassthroughType(DataFlow::TypeCastNode sink, PassthroughTypeName name) {
exists(Type typ | exists(Type typ |
@@ -53,7 +53,7 @@ module UntrustedToPassthroughTypeConversionConfig implements DataFlow::ConfigSig
} }
/** /**
* Tracks taint flow for reasoning about when an `UntrustedFlowSource` is * Tracks taint flow for reasoning about when a `RemoteFlowSource` is
* converted into a special "passthrough" type which will not be escaped by the * converted into a special "passthrough" type which will not be escaped by the
* template generator; this allows the injection of arbitrary content (html, * template generator; this allows the injection of arbitrary content (html,
* css, js) into the generated output of the templates. * css, js) into the generated output of the templates.
@@ -109,13 +109,13 @@ predicate isSinkToTemplateExec(DataFlow::Node sink, DataFlow::CallNode call) {
} }
module FromUntrustedToTemplateExecutionCallConfig implements DataFlow::ConfigSig { module FromUntrustedToTemplateExecutionCallConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource } predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { isSinkToTemplateExec(sink, _) } predicate isSink(DataFlow::Node sink) { isSinkToTemplateExec(sink, _) }
} }
/** /**
* Tracks taint flow from an `UntrustedFlowSource` into a template executor * Tracks taint flow from a `RemoteFlowSource` into a template executor
* call. * call.
*/ */
module FromUntrustedToTemplateExecutionCallFlow = module FromUntrustedToTemplateExecutionCallFlow =

View File

@@ -52,7 +52,7 @@ deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "Condtional Expression Check Bypass" } Configuration() { this = "Condtional Expression Check Bypass" }
override predicate isSource(DataFlow::Node source) { override predicate isSource(DataFlow::Node source) {
source instanceof UntrustedFlowSource source instanceof RemoteFlowSource
or or
exists(DataFlow::FieldReadNode f | exists(DataFlow::FieldReadNode f |
f.getField().hasQualifiedName("net/http", "Request", "Host") f.getField().hasQualifiedName("net/http", "Request", "Host")
@@ -71,7 +71,7 @@ deprecated class Configuration extends TaintTracking::Configuration {
private module Config implements DataFlow::ConfigSig { private module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { predicate isSource(DataFlow::Node source) {
source instanceof UntrustedFlowSource source instanceof RemoteFlowSource
or or
exists(DataFlow::FieldReadNode f | exists(DataFlow::FieldReadNode f |
f.getField().hasQualifiedName("net/http", "Request", "Host") f.getField().hasQualifiedName("net/http", "Request", "Host")

View File

@@ -14,7 +14,7 @@ import go
module Config implements DataFlow::ConfigSig { module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { predicate isSource(DataFlow::Node source) {
source instanceof UntrustedFlowSource source instanceof RemoteFlowSource
or or
source = any(Field f | f.hasQualifiedName("net/http", "Request", "Host")).getARead() source = any(Field f | f.hasQualifiedName("net/http", "Request", "Host")).getARead()
} }

View File

@@ -87,10 +87,15 @@ module ServerSideRequestForgery {
/** An outgoing sanitizer edge for request forgery vulnerabilities. */ /** An outgoing sanitizer edge for request forgery vulnerabilities. */
abstract class SanitizerEdge extends DataFlow::Node { } abstract class SanitizerEdge extends DataFlow::Node { }
/**
* DEPRECATED: Use `RemoteFlowSource` or `Source` instead.
*/
deprecated class UntrustedFlowAsSource = RemoteFlowAsSource;
/** /**
* An user controlled input, considered as a flow source for request forgery. * An user controlled input, considered as a flow source for request forgery.
*/ */
class UntrustedFlowAsSource extends Source instanceof UntrustedFlowSource { } private class RemoteFlowAsSource extends Source instanceof RemoteFlowSource { }
/** /**
* The URL of an HTTP request, viewed as a sink for request forgery. * The URL of an HTTP request, viewed as a sink for request forgery.

View File

@@ -52,7 +52,7 @@ class AllowCredentialsHeaderWrite extends Http::HeaderWrite {
} }
module UntrustedToAllowOriginHeaderConfig implements DataFlow::ConfigSig { module UntrustedToAllowOriginHeaderConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource } predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
additional predicate isSinkHW(DataFlow::Node sink, AllowOriginHeaderWrite hw) { additional predicate isSinkHW(DataFlow::Node sink, AllowOriginHeaderWrite hw) {
sink = hw.getValue() sink = hw.getValue()
@@ -70,7 +70,7 @@ module UntrustedToAllowOriginHeaderConfig implements DataFlow::ConfigSig {
} }
module UntrustedToAllowOriginConfigConfig implements DataFlow::ConfigSig { module UntrustedToAllowOriginConfigConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource } predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
additional predicate isSinkWrite(DataFlow::Node sink, GinCors::AllowOriginsWrite w) { sink = w } additional predicate isSinkWrite(DataFlow::Node sink, GinCors::AllowOriginsWrite w) { sink = w }
@@ -78,13 +78,13 @@ module UntrustedToAllowOriginConfigConfig implements DataFlow::ConfigSig {
} }
/** /**
* Tracks taint flowfor reasoning about when an `UntrustedFlowSource` flows to * Tracks taint flowfor reasoning about when a `RemoteFlowSource` flows to
* a `HeaderWrite` that writes an `Access-Control-Allow-Origin` header's value. * a `HeaderWrite` that writes an `Access-Control-Allow-Origin` header's value.
*/ */
module UntrustedToAllowOriginHeaderFlow = TaintTracking::Global<UntrustedToAllowOriginHeaderConfig>; module UntrustedToAllowOriginHeaderFlow = TaintTracking::Global<UntrustedToAllowOriginHeaderConfig>;
/** /**
* Tracks taint flowfor reasoning about when an `UntrustedFlowSource` flows to * Tracks taint flowfor reasoning about when a `RemoteFlowSource` flows to
* a `AllowOriginsWrite` that writes an `Access-Control-Allow-Origin` header's value. * a `AllowOriginsWrite` that writes an `Access-Control-Allow-Origin` header's value.
*/ */
module UntrustedToAllowOriginConfigFlow = TaintTracking::Global<UntrustedToAllowOriginConfigConfig>; module UntrustedToAllowOriginConfigFlow = TaintTracking::Global<UntrustedToAllowOriginConfigConfig>;
@@ -121,7 +121,7 @@ predicate allowCredentialsIsSetToTrue(DataFlow::ExprNode allowOriginHW) {
/** /**
* Holds if the provided `allowOriginHW` HeaderWrite's value is set using an * Holds if the provided `allowOriginHW` HeaderWrite's value is set using an
* UntrustedFlowSource. * RemoteFlowSource.
* The `message` parameter is populated with the warning message to be returned by the query. * The `message` parameter is populated with the warning message to be returned by the query.
*/ */
predicate flowsFromUntrustedToAllowOrigin(DataFlow::ExprNode allowOriginHW, string message) { predicate flowsFromUntrustedToAllowOrigin(DataFlow::ExprNode allowOriginHW, string message) {
@@ -169,7 +169,7 @@ class MapRead extends DataFlow::ElementReadNode {
} }
module FromUntrustedConfig implements DataFlow::ConfigSig { module FromUntrustedConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource } predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { isSinkCgn(sink, _) } predicate isSink(DataFlow::Node sink) { isSinkCgn(sink, _) }
@@ -208,13 +208,13 @@ module FromUntrustedConfig implements DataFlow::ConfigSig {
} }
/** /**
* Tracks taint flow for reasoning about when an `UntrustedFlowSource` flows * Tracks taint flow for reasoning about when a `RemoteFlowSource` flows
* somewhere. * somewhere.
*/ */
module FromUntrustedFlow = TaintTracking::Global<FromUntrustedConfig>; module FromUntrustedFlow = TaintTracking::Global<FromUntrustedConfig>;
/** /**
* Holds if the provided `allowOriginHW` is also destination of a `UntrustedFlowSource`. * Holds if the provided `allowOriginHW` is also destination of a `RemoteFlowSource`.
*/ */
predicate flowsToGuardedByCheckOnUntrusted(DataFlow::ExprNode allowOriginHW) { predicate flowsToGuardedByCheckOnUntrusted(DataFlow::ExprNode allowOriginHW) {
exists(DataFlow::Node sink, ControlFlow::ConditionGuardNode cgn | exists(DataFlow::Node sink, ControlFlow::ConditionGuardNode cgn |

View File

@@ -2,8 +2,8 @@
"Name": "CleverGo", "Name": "CleverGo",
"Models": [ "Models": [
{ {
"Name": "UntrustedSources", "Name": "RemoteSources",
"Kind": "UntrustedFlowSource", "Kind": "RemoteFlowSource",
"Methods": [ "Methods": [
{ {
"Name": "{source:[](Param|Result|Fields|Type)} \u003c- $source", "Name": "{source:[](Param|Result|Fields|Type)} \u003c- $source",

View File

@@ -14,10 +14,10 @@ private module CleverGo {
} }
/** /**
* Provides models of untrusted flow sources. * Provides models of remote flow sources.
*/ */
private class UntrustedSources extends UntrustedFlowSource::Range { private class RemoteSources extends RemoteFlowSource::Range {
UntrustedSources() { RemoteSources() {
// Methods on types of package: clevergo.tech/clevergo@v0.5.2 // Methods on types of package: clevergo.tech/clevergo@v0.5.2
exists(string receiverName, string methodName, Method mtd, FunctionOutput out | exists(string receiverName, string methodName, Method mtd, FunctionOutput out |
this = out.getExitNode(mtd.getACall()) and this = out.getExitNode(mtd.getACall()) and

View File

@@ -4,7 +4,7 @@
import go import go
class MimeMultipartFileHeader extends UntrustedFlowSource::Range { class MimeMultipartFileHeader extends RemoteFlowSource::Range {
MimeMultipartFileHeader() { MimeMultipartFileHeader() {
exists(DataFlow::FieldReadNode frn | this = frn | exists(DataFlow::FieldReadNode frn | this = frn |
frn.getField().hasQualifiedName("mime/multipart", "FileHeader", ["Filename", "Header"]) frn.getField().hasQualifiedName("mime/multipart", "FileHeader", ["Filename", "Header"])
@@ -29,7 +29,7 @@ module DecompressionBomb {
class FlowState = DecompressionBombs::FlowState; class FlowState = DecompressionBombs::FlowState;
predicate isSource(DataFlow::Node source, FlowState state) { predicate isSource(DataFlow::Node source, FlowState state) {
source instanceof UntrustedFlowSource and source instanceof RemoteFlowSource and
state = "" state = ""
} }

View File

@@ -728,8 +728,8 @@
] ]
}, },
{ {
"Name": "UntrustedFlowSources", "Name": "RemoteFlowSources",
"Kind": "UntrustedFlowSource", "Kind": "RemoteFlowSource",
"Methods": [ "Methods": [
{ {
"Name": "{source:[](Param|Result|Fields|Type)} \u003c- $source", "Name": "{source:[](Param|Result|Fields|Type)} \u003c- $source",

View File

@@ -293,10 +293,10 @@ private module Fiber {
} }
/** /**
* Provides models of untrusted flow sources. * Provides models of remote flow sources.
*/ */
private class UntrustedFlowSources extends UntrustedFlowSource::Range { private class RemoteFlowSources extends RemoteFlowSource::Range {
UntrustedFlowSources() { RemoteFlowSources() {
// Methods on types of package: github.com/gofiber/fiber@v1.14.6 // Methods on types of package: github.com/gofiber/fiber@v1.14.6
exists(string receiverName, string methodName, Method mtd, FunctionOutput out | exists(string receiverName, string methodName, Method mtd, FunctionOutput out |
this = out.getExitNode(mtd.getACall()) and this = out.getExitNode(mtd.getACall()) and

View File

@@ -5,110 +5,110 @@ package main
import "clevergo.tech/clevergo" import "clevergo.tech/clevergo"
// Package clevergo.tech/clevergo@v0.5.2 // Package clevergo.tech/clevergo@v0.5.2
func UntrustedSources_ClevergoTechClevergoV052() { func RemoteSources_ClevergoTechClevergoV052() {
// Untrusted flow sources from method calls. // Remote flow sources from method calls.
{ {
// Untrusted flow sources from method calls on clevergo.tech/clevergo.Context. // Remote flow sources from method calls on clevergo.tech/clevergo.Context.
{ {
// func (*Context).BasicAuth() (username string, password string, ok bool) // func (*Context).BasicAuth() (username string, password string, ok bool)
{ {
var receiverContext656 clevergo.Context var receiverContext656 clevergo.Context
resultUsername414, resultPassword518, _ := receiverContext656.BasicAuth() resultUsername414, resultPassword518, _ := receiverContext656.BasicAuth()
sink(resultUsername414) // $ untrustedFlowSource sink(resultUsername414) // $ remoteFlowSource
sink(resultPassword518) // $ untrustedFlowSource sink(resultPassword518) // $ remoteFlowSource
} }
// func (*Context).Decode(v interface{}) (err error) // func (*Context).Decode(v interface{}) (err error)
{ {
var receiverContext650 clevergo.Context var receiverContext650 clevergo.Context
var paramV784 interface{} var paramV784 interface{}
receiverContext650.Decode(paramV784) receiverContext650.Decode(paramV784)
sink(paramV784) // $ untrustedFlowSource sink(paramV784) // $ remoteFlowSource
} }
// func (*Context).DefaultQuery(key string, defaultVlue string) string // func (*Context).DefaultQuery(key string, defaultVlue string) string
{ {
var receiverContext957 clevergo.Context var receiverContext957 clevergo.Context
result520 := receiverContext957.DefaultQuery("", "") result520 := receiverContext957.DefaultQuery("", "")
sink(result520) // $ untrustedFlowSource sink(result520) // $ remoteFlowSource
} }
// func (*Context).FormValue(key string) string // func (*Context).FormValue(key string) string
{ {
var receiverContext443 clevergo.Context var receiverContext443 clevergo.Context
result127 := receiverContext443.FormValue("") result127 := receiverContext443.FormValue("")
sink(result127) // $ untrustedFlowSource sink(result127) // $ remoteFlowSource
} }
// func (*Context).GetHeader(name string) string // func (*Context).GetHeader(name string) string
{ {
var receiverContext483 clevergo.Context var receiverContext483 clevergo.Context
result989 := receiverContext483.GetHeader("") result989 := receiverContext483.GetHeader("")
sink(result989) // $ untrustedFlowSource sink(result989) // $ remoteFlowSource
} }
// func (*Context).PostFormValue(key string) string // func (*Context).PostFormValue(key string) string
{ {
var receiverContext982 clevergo.Context var receiverContext982 clevergo.Context
result417 := receiverContext982.PostFormValue("") result417 := receiverContext982.PostFormValue("")
sink(result417) // $ untrustedFlowSource sink(result417) // $ remoteFlowSource
} }
// func (*Context).QueryParam(key string) string // func (*Context).QueryParam(key string) string
{ {
var receiverContext584 clevergo.Context var receiverContext584 clevergo.Context
result991 := receiverContext584.QueryParam("") result991 := receiverContext584.QueryParam("")
sink(result991) // $ untrustedFlowSource sink(result991) // $ remoteFlowSource
} }
// func (*Context).QueryParams() net/url.Values // func (*Context).QueryParams() net/url.Values
{ {
var receiverContext881 clevergo.Context var receiverContext881 clevergo.Context
result186 := receiverContext881.QueryParams() result186 := receiverContext881.QueryParams()
sink(result186) // $ untrustedFlowSource sink(result186) // $ remoteFlowSource
} }
// func (*Context).QueryString() string // func (*Context).QueryString() string
{ {
var receiverContext284 clevergo.Context var receiverContext284 clevergo.Context
result908 := receiverContext284.QueryString() result908 := receiverContext284.QueryString()
sink(result908) // $ untrustedFlowSource sink(result908) // $ remoteFlowSource
} }
} }
// Untrusted flow sources from method calls on clevergo.tech/clevergo.Params. // Remote flow sources from method calls on clevergo.tech/clevergo.Params.
{ {
// func (Params).String(name string) string // func (Params).String(name string) string
{ {
var receiverParams137 clevergo.Params var receiverParams137 clevergo.Params
result494 := receiverParams137.String("") result494 := receiverParams137.String("")
sink(result494) // $ untrustedFlowSource sink(result494) // $ remoteFlowSource
} }
} }
} }
// Untrusted flow sources from interface method calls. // Remote flow sources from interface method calls.
{ {
// Untrusted flow sources from method calls on clevergo.tech/clevergo.Decoder interface. // Remote flow sources from method calls on clevergo.tech/clevergo.Decoder interface.
{ {
// func (Decoder).Decode(req *net/http.Request, v interface{}) error // func (Decoder).Decode(req *net/http.Request, v interface{}) error
{ {
var receiverDecoder873 clevergo.Decoder var receiverDecoder873 clevergo.Decoder
var paramV599 interface{} var paramV599 interface{}
receiverDecoder873.Decode(nil, paramV599) receiverDecoder873.Decode(nil, paramV599)
sink(paramV599) // $ untrustedFlowSource sink(paramV599) // $ remoteFlowSource
} }
} }
} }
// Untrusted flow sources from struct fields. // Remote flow sources from struct fields.
{ {
// Untrusted flow sources from clevergo.tech/clevergo.Context struct fields. // Remote flow sources from clevergo.tech/clevergo.Context struct fields.
{ {
structContext409 := new(clevergo.Context) structContext409 := new(clevergo.Context)
sink(structContext409.Params) // $ untrustedFlowSource sink(structContext409.Params) // $ remoteFlowSource
} }
// Untrusted flow sources from clevergo.tech/clevergo.Param struct fields. // Remote flow sources from clevergo.tech/clevergo.Param struct fields.
{ {
structParam246 := new(clevergo.Param) structParam246 := new(clevergo.Param)
sink(structParam246.Key) // $ untrustedFlowSource sink(structParam246.Key) // $ remoteFlowSource
sink(structParam246.Value) // $ untrustedFlowSource sink(structParam246.Value) // $ remoteFlowSource
} }
} }
// Untrusted flow sources from types. // Remote flow sources from types.
{ {
{ {
var typeParams898 clevergo.Params var typeParams898 clevergo.Params
sink(typeParams898) // $ untrustedFlowSource sink(typeParams898) // $ remoteFlowSource
} }
} }
} }

View File

@@ -2,15 +2,15 @@ import go
import TestUtilities.InlineExpectationsTest import TestUtilities.InlineExpectationsTest
import experimental.frameworks.CleverGo import experimental.frameworks.CleverGo
module UntrustedFlowSourceTest implements TestSig { module RemoteFlowSourceTest implements TestSig {
string getARelevantTag() { result = "untrustedFlowSource" } string getARelevantTag() { result = "remoteFlowSource" }
predicate hasActualResult(Location location, string element, string tag, string value) { predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "untrustedFlowSource" and tag = "remoteFlowSource" and
exists(DataFlow::CallNode sinkCall, DataFlow::ArgumentNode arg | exists(DataFlow::CallNode sinkCall, DataFlow::ArgumentNode arg |
sinkCall.getCalleeName() = "sink" and sinkCall.getCalleeName() = "sink" and
arg = sinkCall.getAnArgument() and arg = sinkCall.getAnArgument() and
arg.getAPredecessor*() instanceof UntrustedFlowSource arg.getAPredecessor*() instanceof RemoteFlowSource
| |
element = arg.toString() and element = arg.toString() and
value = "" and value = "" and
@@ -20,4 +20,4 @@ module UntrustedFlowSourceTest implements TestSig {
} }
} }
import MakeTest<UntrustedFlowSourceTest> import MakeTest<RemoteFlowSourceTest>

View File

@@ -55,7 +55,7 @@ func TaintTracking_ClevergoTechClevergoV052() {
{ {
fromParams396 := source().(clevergo.Params) fromParams396 := source().(clevergo.Params)
intoString707 := fromParams396.String("") intoString707 := fromParams396.String("")
sink(intoString707) // $ hasTaintFlow="intoString707" untrustedFlowSource sink(intoString707) // $ hasTaintFlow="intoString707" remoteFlowSource
} }
} }
} }
@@ -69,7 +69,7 @@ func TaintTracking_ClevergoTechClevergoV052() {
var intoInterface718 interface{} var intoInterface718 interface{}
var mediumObjCQL clevergo.Decoder var mediumObjCQL clevergo.Decoder
mediumObjCQL.Decode(fromRequest912, intoInterface718) mediumObjCQL.Decode(fromRequest912, intoInterface718)
sink(intoInterface718) // $ hasTaintFlow="intoInterface718" untrustedFlowSource sink(intoInterface718) // $ hasTaintFlow="intoInterface718" remoteFlowSource
} }
} }
// Taint-tracking through method calls on clevergo.tech/clevergo.Renderer interface. // Taint-tracking through method calls on clevergo.tech/clevergo.Renderer interface.

View File

@@ -5,132 +5,132 @@ package main
import "github.com/gofiber/fiber" import "github.com/gofiber/fiber"
// Package github.com/gofiber/fiber@v1.14.6 // Package github.com/gofiber/fiber@v1.14.6
func UntrustedFlowSources_GithubComGofiberFiberV1146() { func RemoteFlowSources_GithubComGofiberFiberV1146() {
// Untrusted flow sources from method calls. // Remote flow sources from method calls.
{ {
// Untrusted flow sources from method calls on github.com/gofiber/fiber.Ctx. // Remote flow sources from method calls on github.com/gofiber/fiber.Ctx.
{ {
// func (*Ctx).BaseURL() string // func (*Ctx).BaseURL() string
{ {
var receiverCtx273 fiber.Ctx var receiverCtx273 fiber.Ctx
result982 := receiverCtx273.BaseURL() result982 := receiverCtx273.BaseURL()
sink(result982) // $ untrustedFlowSource sink(result982) // $ remoteFlowSource
} }
// func (*Ctx).Body() string // func (*Ctx).Body() string
{ {
var receiverCtx458 fiber.Ctx var receiverCtx458 fiber.Ctx
result506 := receiverCtx458.Body() result506 := receiverCtx458.Body()
sink(result506) // $ untrustedFlowSource sink(result506) // $ remoteFlowSource
} }
// func (*Ctx).BodyParser(out interface{}) error // func (*Ctx).BodyParser(out interface{}) error
{ {
var receiverCtx213 fiber.Ctx var receiverCtx213 fiber.Ctx
var paramOut468 interface{} var paramOut468 interface{}
receiverCtx213.BodyParser(paramOut468) receiverCtx213.BodyParser(paramOut468)
sink(paramOut468) // $ untrustedFlowSource sink(paramOut468) // $ remoteFlowSource
} }
// func (*Ctx).Cookies(key string, defaultValue ...string) string // func (*Ctx).Cookies(key string, defaultValue ...string) string
{ {
var receiverCtx219 fiber.Ctx var receiverCtx219 fiber.Ctx
result265 := receiverCtx219.Cookies("", "") result265 := receiverCtx219.Cookies("", "")
sink(result265) // $ untrustedFlowSource sink(result265) // $ remoteFlowSource
} }
// func (*Ctx).FormFile(key string) (*mime/multipart.FileHeader, error) // func (*Ctx).FormFile(key string) (*mime/multipart.FileHeader, error)
{ {
var receiverCtx971 fiber.Ctx var receiverCtx971 fiber.Ctx
result320, _ := receiverCtx971.FormFile("") result320, _ := receiverCtx971.FormFile("")
sink(result320) // $ untrustedFlowSource sink(result320) // $ remoteFlowSource
} }
// func (*Ctx).FormValue(key string) (value string) // func (*Ctx).FormValue(key string) (value string)
{ {
var receiverCtx545 fiber.Ctx var receiverCtx545 fiber.Ctx
resultValue566 := receiverCtx545.FormValue("") resultValue566 := receiverCtx545.FormValue("")
sink(resultValue566) // $ untrustedFlowSource sink(resultValue566) // $ remoteFlowSource
} }
// func (*Ctx).Get(key string, defaultValue ...string) string // func (*Ctx).Get(key string, defaultValue ...string) string
{ {
var receiverCtx497 fiber.Ctx var receiverCtx497 fiber.Ctx
result274 := receiverCtx497.Get("", "") result274 := receiverCtx497.Get("", "")
sink(result274) // $ untrustedFlowSource sink(result274) // $ remoteFlowSource
} }
// func (*Ctx).Hostname() string // func (*Ctx).Hostname() string
{ {
var receiverCtx783 fiber.Ctx var receiverCtx783 fiber.Ctx
result905 := receiverCtx783.Hostname() result905 := receiverCtx783.Hostname()
sink(result905) // $ untrustedFlowSource sink(result905) // $ remoteFlowSource
} }
// func (*Ctx).Method(override ...string) string // func (*Ctx).Method(override ...string) string
{ {
var receiverCtx389 fiber.Ctx var receiverCtx389 fiber.Ctx
result198 := receiverCtx389.Method("") result198 := receiverCtx389.Method("")
sink(result198) // $ untrustedFlowSource sink(result198) // $ remoteFlowSource
} }
// func (*Ctx).MultipartForm() (*mime/multipart.Form, error) // func (*Ctx).MultipartForm() (*mime/multipart.Form, error)
{ {
var receiverCtx477 fiber.Ctx var receiverCtx477 fiber.Ctx
result544, _ := receiverCtx477.MultipartForm() result544, _ := receiverCtx477.MultipartForm()
sink(result544) // $ untrustedFlowSource sink(result544) // $ remoteFlowSource
} }
// func (*Ctx).OriginalURL() string // func (*Ctx).OriginalURL() string
{ {
var receiverCtx382 fiber.Ctx var receiverCtx382 fiber.Ctx
result715 := receiverCtx382.OriginalURL() result715 := receiverCtx382.OriginalURL()
sink(result715) // $ untrustedFlowSource sink(result715) // $ remoteFlowSource
} }
// func (*Ctx).Params(key string, defaultValue ...string) string // func (*Ctx).Params(key string, defaultValue ...string) string
{ {
var receiverCtx179 fiber.Ctx var receiverCtx179 fiber.Ctx
result366 := receiverCtx179.Params("", "") result366 := receiverCtx179.Params("", "")
sink(result366) // $ untrustedFlowSource sink(result366) // $ remoteFlowSource
} }
// func (*Ctx).Path(override ...string) string // func (*Ctx).Path(override ...string) string
{ {
var receiverCtx648 fiber.Ctx var receiverCtx648 fiber.Ctx
result544 := receiverCtx648.Path("") result544 := receiverCtx648.Path("")
sink(result544) // $ untrustedFlowSource sink(result544) // $ remoteFlowSource
} }
// func (*Ctx).Query(key string, defaultValue ...string) string // func (*Ctx).Query(key string, defaultValue ...string) string
{ {
var receiverCtx754 fiber.Ctx var receiverCtx754 fiber.Ctx
result680 := receiverCtx754.Query("", "") result680 := receiverCtx754.Query("", "")
sink(result680) // $ untrustedFlowSource sink(result680) // $ remoteFlowSource
} }
// func (*Ctx).QueryParser(out interface{}) error // func (*Ctx).QueryParser(out interface{}) error
{ {
var receiverCtx722 fiber.Ctx var receiverCtx722 fiber.Ctx
var paramOut506 interface{} var paramOut506 interface{}
receiverCtx722.QueryParser(paramOut506) receiverCtx722.QueryParser(paramOut506)
sink(paramOut506) // $ untrustedFlowSource sink(paramOut506) // $ remoteFlowSource
} }
// func (*Ctx).Range(size int) (rangeData Range, err error) // func (*Ctx).Range(size int) (rangeData Range, err error)
{ {
var receiverCtx121 fiber.Ctx var receiverCtx121 fiber.Ctx
resultRangeData293, _ := receiverCtx121.Range(0) resultRangeData293, _ := receiverCtx121.Range(0)
sink(resultRangeData293) // $ untrustedFlowSource sink(resultRangeData293) // $ remoteFlowSource
} }
// func (*Ctx).Subdomains(offset ...int) []string // func (*Ctx).Subdomains(offset ...int) []string
{ {
var receiverCtx151 fiber.Ctx var receiverCtx151 fiber.Ctx
result849 := receiverCtx151.Subdomains(0) result849 := receiverCtx151.Subdomains(0)
sink(result849) // $ untrustedFlowSource sink(result849) // $ remoteFlowSource
} }
} }
} }
// Untrusted flow sources from struct fields. // Remote flow sources from struct fields.
{ {
// Untrusted flow sources from github.com/gofiber/fiber.Cookie struct fields. // Remote flow sources from github.com/gofiber/fiber.Cookie struct fields.
{ {
structCookie322 := new(fiber.Cookie) structCookie322 := new(fiber.Cookie)
sink(structCookie322.Domain) // $ untrustedFlowSource sink(structCookie322.Domain) // $ remoteFlowSource
sink(structCookie322.Name) // $ untrustedFlowSource sink(structCookie322.Name) // $ remoteFlowSource
sink(structCookie322.Path) // $ untrustedFlowSource sink(structCookie322.Path) // $ remoteFlowSource
sink(structCookie322.SameSite) // $ untrustedFlowSource sink(structCookie322.SameSite) // $ remoteFlowSource
sink(structCookie322.Value) // $ untrustedFlowSource sink(structCookie322.Value) // $ remoteFlowSource
} }
// Untrusted flow sources from github.com/gofiber/fiber.Error struct fields. // Remote flow sources from github.com/gofiber/fiber.Error struct fields.
{ {
structError339 := new(fiber.Error) structError339 := new(fiber.Error)
sink(structError339.Message) // $ untrustedFlowSource sink(structError339.Message) // $ remoteFlowSource
} }
} }
} }

View File

@@ -2,15 +2,15 @@ import go
import TestUtilities.InlineExpectationsTest import TestUtilities.InlineExpectationsTest
import experimental.frameworks.Fiber import experimental.frameworks.Fiber
module UntrustedFlowSourceTest implements TestSig { module RemoteFlowSourceTest implements TestSig {
string getARelevantTag() { result = "untrustedFlowSource" } string getARelevantTag() { result = "remoteFlowSource" }
predicate hasActualResult(Location location, string element, string tag, string value) { predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "untrustedFlowSource" and tag = "remoteFlowSource" and
exists(DataFlow::CallNode sinkCall, DataFlow::ArgumentNode arg | exists(DataFlow::CallNode sinkCall, DataFlow::ArgumentNode arg |
sinkCall.getCalleeName() = "sink" and sinkCall.getCalleeName() = "sink" and
arg = sinkCall.getAnArgument() and arg = sinkCall.getAnArgument() and
arg.getAPredecessor*() instanceof UntrustedFlowSource arg.getAPredecessor*() instanceof RemoteFlowSource
| |
element = arg.toString() and element = arg.toString() and
value = "" and value = "" and
@@ -20,4 +20,4 @@ module UntrustedFlowSourceTest implements TestSig {
} }
} }
import MakeTest<UntrustedFlowSourceTest> import MakeTest<RemoteFlowSourceTest>

View File

@@ -0,0 +1,3 @@
import go
select any(RemoteFlowSource ufs)

View File

@@ -1,3 +0,0 @@
import go
select any(UntrustedFlowSource ufs)

View File

@@ -6,7 +6,7 @@
import go import go
module Config implements DataFlow::ConfigSig { module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node n) { n instanceof UntrustedFlowSource } predicate isSource(DataFlow::Node n) { n instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node n) { any(ReturnStmt s).getAnExpr() = n.asExpr() } predicate isSink(DataFlow::Node n) { any(ReturnStmt s).getAnExpr() = n.asExpr() }
} }

View File

@@ -2,7 +2,7 @@ import go
import TestUtilities.InlineFlowTest import TestUtilities.InlineFlowTest
module Config implements DataFlow::ConfigSig { module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource } predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { predicate isSink(DataFlow::Node sink) {
exists(Function fn | fn.hasQualifiedName(_, "sink") | sink = fn.getACall().getAnArgument()) exists(Function fn | fn.hasQualifiedName(_, "sink") | sink = fn.getACall().getAnArgument())

View File

@@ -11,7 +11,7 @@ import (
) )
func handler(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) { func handler(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
data := ctx.UserData // $ untrustedflowsource="selection of UserData" data := ctx.UserData // $ remoteflowsource="selection of UserData"
// note no content type result here because we don't seem to extract the value of `ContentTypeHtml` // note no content type result here because we don't seem to extract the value of `ContentTypeHtml`
return r, goproxy.NewResponse(r, goproxy.ContentTypeHtml, http.StatusForbidden, fmt.Sprintf("<body>Bad request: %v</body>", data)) // $ headerwrite=status:403 return r, goproxy.NewResponse(r, goproxy.ContentTypeHtml, http.StatusForbidden, fmt.Sprintf("<body>Bad request: %v</body>", data)) // $ headerwrite=status:403

View File

@@ -1,13 +1,13 @@
import go import go
import TestUtilities.InlineExpectationsTest import TestUtilities.InlineExpectationsTest
module UntrustedFlowSourceTest implements TestSig { module RemoteFlowSourceTest implements TestSig {
string getARelevantTag() { result = "untrustedflowsource" } string getARelevantTag() { result = "remoteflowsource" }
predicate hasActualResult(Location location, string element, string tag, string value) { predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "untrustedflowsource" and tag = "remoteflowsource" and
value = element and value = element and
exists(UntrustedFlowSource src | value = "\"" + src.toString() + "\"" | exists(RemoteFlowSource src | value = "\"" + src.toString() + "\"" |
src.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), src.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) location.getStartColumn(), location.getEndLine(), location.getEndColumn())
) )
@@ -70,4 +70,4 @@ module TaintFlow implements TestSig {
} }
} }
import MakeTest<MergeTests4<UntrustedFlowSourceTest, HeaderWriteTest, LoggerTest, TaintFlow>> import MakeTest<MergeTests4<RemoteFlowSourceTest, HeaderWriteTest, LoggerTest, TaintFlow>>

View File

@@ -6,8 +6,8 @@ class UntrustedFunction extends Function {
UntrustedFunction() { this.getName() = ["getUntrustedString", "getUntrustedBytes"] } UntrustedFunction() { this.getName() = ["getUntrustedString", "getUntrustedBytes"] }
} }
class UntrustedSource extends DataFlow::Node, UntrustedFlowSource::Range { class RemoteSource extends DataFlow::Node, RemoteFlowSource::Range {
UntrustedSource() { this = any(UntrustedFunction f).getACall() } RemoteSource() { this = any(UntrustedFunction f).getACall() }
} }
from CommandInjection::Flow::PathNode source, CommandInjection::Flow::PathNode sink from CommandInjection::Flow::PathNode source, CommandInjection::Flow::PathNode sink

View File

@@ -2,16 +2,16 @@ import go
import TestUtilities.InlineExpectationsTest import TestUtilities.InlineExpectationsTest
module FasthttpTest implements TestSig { module FasthttpTest implements TestSig {
string getARelevantTag() { result = "UntrustedFlowSource" } string getARelevantTag() { result = "RemoteFlowSource" }
predicate hasActualResult(Location location, string element, string tag, string value) { predicate hasActualResult(Location location, string element, string tag, string value) {
exists(UntrustedFlowSource source | exists(RemoteFlowSource source |
source source
.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), .hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
element = source.toString() and element = source.toString() and
value = "\"" + source.toString() + "\"" and value = "\"" + source.toString() + "\"" and
tag = "UntrustedFlowSource" tag = "RemoteFlowSource"
) )
} }
} }

View File

@@ -96,7 +96,7 @@ func main() {
func fasthttpServer() { func fasthttpServer() {
ln, _ := net.Listen("tcp4", "127.0.0.1:8080") ln, _ := net.Listen("tcp4", "127.0.0.1:8080")
requestHandler := func(requestCtx *fasthttp.RequestCtx) { requestHandler := func(requestCtx *fasthttp.RequestCtx) {
filePath := requestCtx.QueryArgs().Peek("filePath") // $ UntrustedFlowSource="call to Peek" filePath := requestCtx.QueryArgs().Peek("filePath") // $ RemoteFlowSource="call to Peek"
// File System Access // File System Access
filePath_string := string(filePath) filePath_string := string(filePath)
_ = requestCtx.Response.SendFile(filePath_string) // $ FileSystemAccess=filePath_string _ = requestCtx.Response.SendFile(filePath_string) // $ FileSystemAccess=filePath_string
@@ -112,67 +112,67 @@ func fasthttpServer() {
dstReader := &bufio.Reader{} dstReader := &bufio.Reader{}
// user controlled methods as source // user controlled methods as source
requestHeader := &fasthttp.RequestHeader{} requestHeader := &fasthttp.RequestHeader{}
requestHeader.Header() // $ UntrustedFlowSource="call to Header" requestHeader.Header() // $ RemoteFlowSource="call to Header"
requestHeader.TrailerHeader() // $ UntrustedFlowSource="call to TrailerHeader" requestHeader.TrailerHeader() // $ RemoteFlowSource="call to TrailerHeader"
requestHeader.String() // $ UntrustedFlowSource="call to String" requestHeader.String() // $ RemoteFlowSource="call to String"
requestHeader.RequestURI() // $ UntrustedFlowSource="call to RequestURI" requestHeader.RequestURI() // $ RemoteFlowSource="call to RequestURI"
requestHeader.Host() // $ UntrustedFlowSource="call to Host" requestHeader.Host() // $ RemoteFlowSource="call to Host"
requestHeader.UserAgent() // $ UntrustedFlowSource="call to UserAgent" requestHeader.UserAgent() // $ RemoteFlowSource="call to UserAgent"
requestHeader.ContentEncoding() // $ UntrustedFlowSource="call to ContentEncoding" requestHeader.ContentEncoding() // $ RemoteFlowSource="call to ContentEncoding"
requestHeader.ContentType() // $ UntrustedFlowSource="call to ContentType" requestHeader.ContentType() // $ RemoteFlowSource="call to ContentType"
requestHeader.Cookie("ACookie") // $ UntrustedFlowSource="call to Cookie" requestHeader.Cookie("ACookie") // $ RemoteFlowSource="call to Cookie"
requestHeader.CookieBytes([]byte("ACookie")) // $ UntrustedFlowSource="call to CookieBytes" requestHeader.CookieBytes([]byte("ACookie")) // $ RemoteFlowSource="call to CookieBytes"
requestHeader.MultipartFormBoundary() // $ UntrustedFlowSource="call to MultipartFormBoundary" requestHeader.MultipartFormBoundary() // $ RemoteFlowSource="call to MultipartFormBoundary"
requestHeader.Peek("AHeaderName") // $ UntrustedFlowSource="call to Peek" requestHeader.Peek("AHeaderName") // $ RemoteFlowSource="call to Peek"
requestHeader.PeekAll("AHeaderName") // $ UntrustedFlowSource="call to PeekAll" requestHeader.PeekAll("AHeaderName") // $ RemoteFlowSource="call to PeekAll"
requestHeader.PeekBytes([]byte("AHeaderName")) // $ UntrustedFlowSource="call to PeekBytes" requestHeader.PeekBytes([]byte("AHeaderName")) // $ RemoteFlowSource="call to PeekBytes"
requestHeader.PeekKeys() // $ UntrustedFlowSource="call to PeekKeys" requestHeader.PeekKeys() // $ RemoteFlowSource="call to PeekKeys"
requestHeader.PeekTrailerKeys() // $ UntrustedFlowSource="call to PeekTrailerKeys" requestHeader.PeekTrailerKeys() // $ RemoteFlowSource="call to PeekTrailerKeys"
requestHeader.Referer() // $ UntrustedFlowSource="call to Referer" requestHeader.Referer() // $ RemoteFlowSource="call to Referer"
requestHeader.RawHeaders() // $ UntrustedFlowSource="call to RawHeaders" requestHeader.RawHeaders() // $ RemoteFlowSource="call to RawHeaders"
// multipart.Form is already implemented // multipart.Form is already implemented
// requestCtx.MultipartForm() // requestCtx.MultipartForm()
requestCtx.URI().Path() // $ UntrustedFlowSource="call to Path" requestCtx.URI().Path() // $ RemoteFlowSource="call to Path"
requestCtx.URI().PathOriginal() // $ UntrustedFlowSource="call to PathOriginal" requestCtx.URI().PathOriginal() // $ RemoteFlowSource="call to PathOriginal"
requestCtx.URI().FullURI() // $ UntrustedFlowSource="call to FullURI" requestCtx.URI().FullURI() // $ RemoteFlowSource="call to FullURI"
requestCtx.URI().LastPathSegment() // $ UntrustedFlowSource="call to LastPathSegment" requestCtx.URI().LastPathSegment() // $ RemoteFlowSource="call to LastPathSegment"
requestCtx.URI().QueryString() // $ UntrustedFlowSource="call to QueryString" requestCtx.URI().QueryString() // $ RemoteFlowSource="call to QueryString"
requestCtx.URI().String() // $ UntrustedFlowSource="call to String" requestCtx.URI().String() // $ RemoteFlowSource="call to String"
//or requestCtx.PostArgs() //or requestCtx.PostArgs()
requestCtx.URI().QueryArgs().Peek("arg1") // $ UntrustedFlowSource="call to Peek" requestCtx.URI().QueryArgs().Peek("arg1") // $ RemoteFlowSource="call to Peek"
requestCtx.URI().QueryArgs().PeekBytes([]byte("arg1")) // $ UntrustedFlowSource="call to PeekBytes" requestCtx.URI().QueryArgs().PeekBytes([]byte("arg1")) // $ RemoteFlowSource="call to PeekBytes"
requestCtx.URI().QueryArgs().PeekMulti("arg1") // $ UntrustedFlowSource="call to PeekMulti" requestCtx.URI().QueryArgs().PeekMulti("arg1") // $ RemoteFlowSource="call to PeekMulti"
requestCtx.URI().QueryArgs().PeekMultiBytes([]byte("arg1")) // $ UntrustedFlowSource="call to PeekMultiBytes" requestCtx.URI().QueryArgs().PeekMultiBytes([]byte("arg1")) // $ RemoteFlowSource="call to PeekMultiBytes"
requestCtx.URI().QueryArgs().QueryString() // $ UntrustedFlowSource="call to QueryString" requestCtx.URI().QueryArgs().QueryString() // $ RemoteFlowSource="call to QueryString"
requestCtx.URI().QueryArgs().String() // $ UntrustedFlowSource="call to String" requestCtx.URI().QueryArgs().String() // $ RemoteFlowSource="call to String"
requestCtx.String() // $ UntrustedFlowSource="call to String" requestCtx.String() // $ RemoteFlowSource="call to String"
requestCtx.Path() // $ UntrustedFlowSource="call to Path" requestCtx.Path() // $ RemoteFlowSource="call to Path"
// multipart.Form is already implemented // multipart.Form is already implemented
// requestCtx.FormFile("FileName") // requestCtx.FormFile("FileName")
// requestCtx.FormValue("ValueName") // requestCtx.FormValue("ValueName")
requestCtx.Referer() // $ UntrustedFlowSource="call to Referer" requestCtx.Referer() // $ RemoteFlowSource="call to Referer"
requestCtx.PostBody() // $ UntrustedFlowSource="call to PostBody" requestCtx.PostBody() // $ RemoteFlowSource="call to PostBody"
requestCtx.RequestBodyStream() // $ UntrustedFlowSource="call to RequestBodyStream" requestCtx.RequestBodyStream() // $ RemoteFlowSource="call to RequestBodyStream"
requestCtx.RequestURI() // $ UntrustedFlowSource="call to RequestURI" requestCtx.RequestURI() // $ RemoteFlowSource="call to RequestURI"
requestCtx.UserAgent() // $ UntrustedFlowSource="call to UserAgent" requestCtx.UserAgent() // $ RemoteFlowSource="call to UserAgent"
requestCtx.Host() // $ UntrustedFlowSource="call to Host" requestCtx.Host() // $ RemoteFlowSource="call to Host"
requestCtx.Request.Host() // $ UntrustedFlowSource="call to Host" requestCtx.Request.Host() // $ RemoteFlowSource="call to Host"
requestCtx.Request.Body() // $ UntrustedFlowSource="call to Body" requestCtx.Request.Body() // $ RemoteFlowSource="call to Body"
requestCtx.Request.RequestURI() // $ UntrustedFlowSource="call to RequestURI" requestCtx.Request.RequestURI() // $ RemoteFlowSource="call to RequestURI"
body1, _ := requestCtx.Request.BodyGunzip() // $ UntrustedFlowSource="... := ...[0]" body1, _ := requestCtx.Request.BodyGunzip() // $ RemoteFlowSource="... := ...[0]"
body2, _ := requestCtx.Request.BodyInflate() // $ UntrustedFlowSource="... := ...[0]" body2, _ := requestCtx.Request.BodyInflate() // $ RemoteFlowSource="... := ...[0]"
body3, _ := requestCtx.Request.BodyUnbrotli() // $ UntrustedFlowSource="... := ...[0]" body3, _ := requestCtx.Request.BodyUnbrotli() // $ RemoteFlowSource="... := ...[0]"
body4, _ := requestCtx.Request.BodyUncompressed() // $ UntrustedFlowSource="... := ...[0]" body4, _ := requestCtx.Request.BodyUncompressed() // $ RemoteFlowSource="... := ...[0]"
fmt.Println(body1, body2, body3, body4) fmt.Println(body1, body2, body3, body4)
requestCtx.Request.BodyStream() // $ UntrustedFlowSource="call to BodyStream" requestCtx.Request.BodyStream() // $ RemoteFlowSource="call to BodyStream"
requestCtx.Request.ReadBody(dstReader, 100, 1000) // $ UntrustedFlowSource="dstReader" requestCtx.Request.ReadBody(dstReader, 100, 1000) // $ RemoteFlowSource="dstReader"
requestCtx.Request.ReadLimitBody(dstReader, 100) // $ UntrustedFlowSource="dstReader" requestCtx.Request.ReadLimitBody(dstReader, 100) // $ RemoteFlowSource="dstReader"
requestCtx.Request.ContinueReadBodyStream(dstReader, 100, true) // $ UntrustedFlowSource="dstReader" requestCtx.Request.ContinueReadBodyStream(dstReader, 100, true) // $ RemoteFlowSource="dstReader"
requestCtx.Request.ContinueReadBody(dstReader, 100) // $ UntrustedFlowSource="dstReader" requestCtx.Request.ContinueReadBody(dstReader, 100) // $ RemoteFlowSource="dstReader"
// Response methods // Response methods
// Xss Sinks Related method // Xss Sinks Related method

View File

@@ -1,3 +1,3 @@
import go import go
select any(UntrustedFlowSource src) select any(RemoteFlowSource src)

View File

@@ -1,11 +1,11 @@
import go import go
import TestUtilities.InlineExpectationsTest import TestUtilities.InlineExpectationsTest
module UntrustedFlowSourceTest implements TestSig { module RemoteFlowSourceTest implements TestSig {
string getARelevantTag() { result = "source" } string getARelevantTag() { result = "source" }
predicate hasActualResult(Location location, string element, string tag, string value) { predicate hasActualResult(Location location, string element, string tag, string value) {
exists(UntrustedFlowSource source | exists(RemoteFlowSource source |
source source
.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), .hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
@@ -16,4 +16,4 @@ module UntrustedFlowSourceTest implements TestSig {
} }
} }
import MakeTest<UntrustedFlowSourceTest> import MakeTest<RemoteFlowSourceTest>

View File

@@ -1,18 +1,18 @@
import go import go
import TestUtilities.InlineExpectationsTest import TestUtilities.InlineExpectationsTest
module UntrustedFlowSourceTest implements TestSig { module RemoteFlowSourceTest implements TestSig {
string getARelevantTag() { result = "UntrustedFlowSource" } string getARelevantTag() { result = "RemoteFlowSource" }
predicate hasActualResult(Location location, string element, string tag, string value) { predicate hasActualResult(Location location, string element, string tag, string value) {
exists(UntrustedFlowSource src | exists(RemoteFlowSource src |
src.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), src.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
element = src.toString() and element = src.toString() and
value = "" and value = "" and
tag = "UntrustedFlowSource" tag = "RemoteFlowSource"
) )
} }
} }
import MakeTest<UntrustedFlowSourceTest> import MakeTest<RemoteFlowSourceTest>

View File

@@ -7,16 +7,16 @@ import (
) )
func sources(ctx *macaron.Context, body *macaron.RequestBody) { func sources(ctx *macaron.Context, body *macaron.RequestBody) {
_ = ctx.AllParams() // $UntrustedFlowSource _ = ctx.AllParams() // $RemoteFlowSource
_ = ctx.GetCookie("") // $UntrustedFlowSource _ = ctx.GetCookie("") // $RemoteFlowSource
_, _ = ctx.GetSecureCookie("") // $UntrustedFlowSource _, _ = ctx.GetSecureCookie("") // $RemoteFlowSource
_, _ = ctx.GetSuperSecureCookie("", "") // $UntrustedFlowSource _, _ = ctx.GetSuperSecureCookie("", "") // $RemoteFlowSource
_, _, _ = ctx.GetFile("") // $UntrustedFlowSource _, _, _ = ctx.GetFile("") // $RemoteFlowSource
_ = ctx.Params("") // $UntrustedFlowSource _ = ctx.Params("") // $RemoteFlowSource
_ = ctx.ParamsEscape("") // $UntrustedFlowSource _ = ctx.ParamsEscape("") // $RemoteFlowSource
_ = ctx.Query("") // $UntrustedFlowSource _ = ctx.Query("") // $RemoteFlowSource
_ = ctx.QueryEscape("") // $UntrustedFlowSource _ = ctx.QueryEscape("") // $RemoteFlowSource
_ = ctx.QueryStrings("") // $UntrustedFlowSource _ = ctx.QueryStrings("") // $RemoteFlowSource
_, _ = body.Bytes() // $UntrustedFlowSource _, _ = body.Bytes() // $RemoteFlowSource
_, _ = body.String() // $UntrustedFlowSource _, _ = body.String() // $RemoteFlowSource
} }

View File

@@ -0,0 +1,3 @@
import go
select any(RemoteFlowSource ufs)

View File

@@ -1,3 +0,0 @@
import go
select any(UntrustedFlowSource ufs)

View File

@@ -8,7 +8,7 @@ class Sink extends DataFlow::Node {
} }
private module TestConfig implements DataFlow::ConfigSig { private module TestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource } predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink } predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
} }