mirror of
https://github.com/github/codeql.git
synced 2026-05-25 00:27:09 +02:00
Merge tag 'codeql-cli/latest' into auto/sync-main-pr
Compatible with the latest released version of the CodeQL CLI
This commit is contained in:
@@ -1,3 +1,17 @@
|
||||
## 2.6.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Data passed to the [NextResponse](https://nextjs.org/docs/app/api-reference/functions/next-response) constructor is now treated as a sink for `js/reflected-xss`.
|
||||
* Data received from [NextRequest](https://nextjs.org/docs/app/api-reference/functions/next-request) and [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) is now treated as a remote user input `source`.
|
||||
* Added support for the `make-dir` package.
|
||||
* Added support for the `open` package.
|
||||
* Added taint propagation for `Uint8Array`, `ArrayBuffer`, `SharedArrayBuffer` and `TextDecoder.decode()`.
|
||||
* Improved detection of `WebSocket` and `SockJS` usage.
|
||||
* Added data received from `WebSocket` clients as a remote flow source.
|
||||
* Added support for additional `mkdirp` methods as sinks in path-injection queries.
|
||||
* Added support for additional `rimraf` methods as sinks in path-injection queries.
|
||||
|
||||
## 2.6.0
|
||||
|
||||
### New Features
|
||||
|
||||
13
javascript/ql/lib/change-notes/released/2.6.1.md
Normal file
13
javascript/ql/lib/change-notes/released/2.6.1.md
Normal file
@@ -0,0 +1,13 @@
|
||||
## 2.6.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Data passed to the [NextResponse](https://nextjs.org/docs/app/api-reference/functions/next-response) constructor is now treated as a sink for `js/reflected-xss`.
|
||||
* Data received from [NextRequest](https://nextjs.org/docs/app/api-reference/functions/next-request) and [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) is now treated as a remote user input `source`.
|
||||
* Added support for the `make-dir` package.
|
||||
* Added support for the `open` package.
|
||||
* Added taint propagation for `Uint8Array`, `ArrayBuffer`, `SharedArrayBuffer` and `TextDecoder.decode()`.
|
||||
* Improved detection of `WebSocket` and `SockJS` usage.
|
||||
* Added data received from `WebSocket` clients as a remote flow source.
|
||||
* Added support for additional `mkdirp` methods as sinks in path-injection queries.
|
||||
* Added support for additional `rimraf` methods as sinks in path-injection queries.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 2.6.0
|
||||
lastReleaseVersion: 2.6.1
|
||||
|
||||
6
javascript/ql/lib/ext/make-dir.model.yml
Normal file
6
javascript/ql/lib/ext/make-dir.model.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["make-dir", "Member[makeDirectory,makeDirectorySync].Argument[0]", "path-injection"]
|
||||
7
javascript/ql/lib/ext/mkdirp.model.yml
Normal file
7
javascript/ql/lib/ext/mkdirp.model.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["mkdirp", "Member[nativeSync,native,manual,manualSync,mkdirpNative,mkdirpManual,mkdirpManualSync,mkdirpNativeSync,mkdirpSync,sync].Argument[0]", "path-injection"]
|
||||
- ["mkdirp", "Argument[0]", "path-injection"]
|
||||
7
javascript/ql/lib/ext/open.model.yml
Normal file
7
javascript/ql/lib/ext/open.model.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["open", "Argument[0]", "path-injection"]
|
||||
- ["open", "Member[openApp].Argument[0]", "path-injection"]
|
||||
8
javascript/ql/lib/ext/rimraf.model.yml
Normal file
8
javascript/ql/lib/ext/rimraf.model.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["rimraf", "Member[sync,native,manual,windows,moveRemove,posix].Argument[0]", "path-injection"]
|
||||
- ["rimraf", "Member[rimrafSync,nativeSync,manualSync,windowsSync,moveRemoveSync,posixSync].Argument[0]", "path-injection"]
|
||||
- ["rimraf", "Member[native,manual,windows,moveRemove,posix].Member[sync].Argument[0]", "path-injection"]
|
||||
@@ -136,6 +136,7 @@ import semmle.javascript.frameworks.UriLibraries
|
||||
import semmle.javascript.frameworks.Vue
|
||||
import semmle.javascript.frameworks.Vuex
|
||||
import semmle.javascript.frameworks.Webix
|
||||
import semmle.javascript.frameworks.WebResponse
|
||||
import semmle.javascript.frameworks.WebSocket
|
||||
import semmle.javascript.frameworks.XmlParsers
|
||||
import semmle.javascript.frameworks.xUnit
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/javascript-all
|
||||
version: 2.6.0
|
||||
version: 2.6.1
|
||||
groups: javascript
|
||||
dbscheme: semmlecode.javascript.dbscheme
|
||||
extractor: javascript
|
||||
|
||||
@@ -318,6 +318,11 @@ module API {
|
||||
Node getParameter(int i) {
|
||||
Stages::ApiStage::ref() and
|
||||
result = this.getASuccessor(Label::parameter(i))
|
||||
or
|
||||
exists(int spreadIndex, string arrayProp |
|
||||
result = this.getASuccessor(Label::spreadArgument(spreadIndex)).getMember(arrayProp) and
|
||||
i = spreadIndex + arrayProp.toInt()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -860,6 +865,23 @@ module API {
|
||||
.getStaticMember(name, DataFlow::MemberKind::getter())
|
||||
.getAReturn()
|
||||
)
|
||||
or
|
||||
// Handle rest parameters escaping into external code. For example:
|
||||
//
|
||||
// function foo(...rest) {
|
||||
// externalFunc(rest);
|
||||
// }
|
||||
//
|
||||
// Here, 'rest' reaches a def-node at the call to externalFunc, so we need to ensure
|
||||
// the arguments passed to 'foo' are stored in the 'rest' array.
|
||||
exists(Function fun, DataFlow::InvokeNode invoke, int argIndex, Parameter rest |
|
||||
fun.getRestParameter() = rest and
|
||||
rest.flow() = pred and
|
||||
invoke.getACallee() = fun and
|
||||
invoke.getArgument(argIndex) = rhs and
|
||||
argIndex >= rest.getIndex() and
|
||||
lbl = Label::member((argIndex - rest.getIndex()).toString())
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::ClassNode cls, string name |
|
||||
@@ -888,6 +910,11 @@ module API {
|
||||
i = -1 and lbl = Label::receiver()
|
||||
)
|
||||
or
|
||||
exists(int i |
|
||||
spreadArgumentPassing(base, i, rhs) and
|
||||
lbl = Label::spreadArgument(i)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::SourceNode src, DataFlow::PropWrite pw |
|
||||
use(base, src) and pw = trackUseNode(src).getAPropertyWrite() and rhs = pw.getRhs()
|
||||
|
|
||||
@@ -931,6 +958,29 @@ module API {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private int firstSpreadIndex(InvokeExpr expr) {
|
||||
result = min(int i | expr.getArgument(i) instanceof SpreadElement)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private InvokeExpr getAnInvocationWithSpread(DataFlow::SourceNode node, int i) {
|
||||
result = node.getAnInvocation().asExpr() and
|
||||
i = firstSpreadIndex(result)
|
||||
}
|
||||
|
||||
private predicate spreadArgumentPassing(TApiNode base, int i, DataFlow::Node spreadArray) {
|
||||
exists(
|
||||
DataFlow::Node use, DataFlow::SourceNode pred, int bound, InvokeExpr invoke, int spreadPos
|
||||
|
|
||||
use(base, use) and
|
||||
pred = trackUseNode(use, _, bound, "") and
|
||||
invoke = getAnInvocationWithSpread(pred, spreadPos) and
|
||||
spreadArray = invoke.getArgument(spreadPos).(SpreadElement).getOperand().flow() and
|
||||
i = bound + spreadPos
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `rhs` is the right-hand side of a definition of node `nd`.
|
||||
*/
|
||||
@@ -1579,6 +1629,9 @@ module API {
|
||||
/** Gets the edge label for the receiver. */
|
||||
LabelReceiver receiver() { any() }
|
||||
|
||||
/** Gets the edge label for a spread argument passed at index `i`. */
|
||||
LabelSpreadArgument spreadArgument(int i) { result.getIndex() = i }
|
||||
|
||||
/** Gets the `return` edge label. */
|
||||
LabelReturn return() { any() }
|
||||
|
||||
@@ -1628,6 +1681,7 @@ module API {
|
||||
} or
|
||||
MkLabelReceiver() or
|
||||
MkLabelReturn() or
|
||||
MkLabelSpreadArgument(int index) { index = [0 .. 10] } or
|
||||
MkLabelDecoratedClass() or
|
||||
MkLabelDecoratedMember() or
|
||||
MkLabelDecoratedParameter() or
|
||||
@@ -1743,6 +1797,21 @@ module API {
|
||||
override string toString() { result = "getReceiver()" }
|
||||
}
|
||||
|
||||
/** A label representing an array passed as a spread argument at a given index. */
|
||||
class LabelSpreadArgument extends ApiLabel, MkLabelSpreadArgument {
|
||||
private int index;
|
||||
|
||||
LabelSpreadArgument() { this = MkLabelSpreadArgument(index) }
|
||||
|
||||
/** Gets the argument index at which the spread argument appears. */
|
||||
int getIndex() { result = index }
|
||||
|
||||
override string toString() {
|
||||
// Note: This refers to the internal edge that has no corresponding method on API::Node
|
||||
result = "getSpreadArgument(" + index + ")"
|
||||
}
|
||||
}
|
||||
|
||||
/** A label for a function that is a wrapper around another function. */
|
||||
class LabelForwardingFunction extends ApiLabel, MkLabelForwardingFunction {
|
||||
override string toString() { result = "getForwardingFunction()" }
|
||||
|
||||
@@ -247,7 +247,7 @@ module DOM {
|
||||
]
|
||||
|
|
||||
(
|
||||
result = documentRef().getAMethodCall(collectionName) or
|
||||
result = domValueRef().getAMethodCall(collectionName) or
|
||||
result = DataFlow::globalVarRef(collectionName).getACall()
|
||||
)
|
||||
)
|
||||
@@ -441,10 +441,12 @@ module DOM {
|
||||
DataFlow::SourceNode domValueRef() {
|
||||
result = domValueRef(DataFlow::TypeTracker::end())
|
||||
or
|
||||
result.hasUnderlyingType("Element")
|
||||
result.hasUnderlyingType(["Element", "HTMLCollection", "HTMLCollectionOf"])
|
||||
or
|
||||
result.hasUnderlyingType(any(string s | s.matches("HTML%Element")))
|
||||
or
|
||||
result = documentRef()
|
||||
or
|
||||
exists(DataFlow::ClassNode cls |
|
||||
cls.getASuperClassNode().getALocalSource() =
|
||||
DataFlow::globalVarRef(any(string s | s.matches("HTML%Element"))) and
|
||||
|
||||
@@ -254,6 +254,12 @@ private module Cached {
|
||||
cached
|
||||
predicate invocation(DataFlow::SourceNode func, DataFlow::InvokeNode invoke) {
|
||||
hasLocalSource(invoke.getCalleeNode(), func)
|
||||
or
|
||||
exists(ClassDefinition cls, SuperCall call |
|
||||
hasLocalSource(cls.getSuperClass().flow(), func) and
|
||||
call.getBinder() = cls.getConstructor().getBody() and
|
||||
invoke = call.flow()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -427,16 +427,3 @@ class Chokidar extends FileNameProducer, FileSystemAccess, API::CallNode {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the [`mkdirp`](https://www.npmjs.com/package/mkdirp) library.
|
||||
*/
|
||||
private class Mkdirp extends FileSystemAccess, API::CallNode {
|
||||
Mkdirp() {
|
||||
this = API::moduleImport("mkdirp").getACall()
|
||||
or
|
||||
this = API::moduleImport("mkdirp").getMember("sync").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
@@ -108,6 +108,12 @@ module Http {
|
||||
* Gets the route handler that sends this expression.
|
||||
*/
|
||||
abstract RouteHandler getRouteHandler();
|
||||
|
||||
/**
|
||||
* Gets a header definition associated with this response body, if it they are provided
|
||||
* by the same call.
|
||||
*/
|
||||
HeaderDefinition getAnAssociatedHeaderDefinition() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -213,10 +213,12 @@ module NextJS {
|
||||
/**
|
||||
* Gets a folder that contains API endpoints for a Next.js application.
|
||||
* These API endpoints act as Express-like route-handlers.
|
||||
* It matches both the Pages Router (`pages/api/`) Next.js 12 or earlier and
|
||||
* the App Router (`app/api/`) Next.js 13+ structures.
|
||||
*/
|
||||
Folder apiFolder() {
|
||||
result = getANextPackage().getFile().getParentContainer().getFolder("pages").getFolder("api")
|
||||
or
|
||||
result =
|
||||
getANextPackage().getFile().getParentContainer().getFolder(["pages", "app"]).getFolder("api") or
|
||||
result = apiFolder().getAFolder()
|
||||
}
|
||||
|
||||
@@ -271,4 +273,64 @@ module NextJS {
|
||||
override string getCredentialsKind() { result = "jwt key" }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A route handler for Next.js 13+ App Router API endpoints, which are defined by exporting
|
||||
* HTTP method functions (like `GET`, `POST`, `PUT`, `DELETE`) from route.js files inside
|
||||
* the `app/api/` directory.
|
||||
*/
|
||||
class NextAppRouteHandler extends DataFlow::FunctionNode, Http::Servers::StandardRouteHandler {
|
||||
NextAppRouteHandler() {
|
||||
exists(Module mod |
|
||||
mod.getFile().getParentContainer() = apiFolder() or
|
||||
mod.getFile().getStem() = "middleware"
|
||||
|
|
||||
this =
|
||||
mod.getAnExportedValue([any(Http::RequestMethodName m), "middleware"]).getAFunctionValue()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the request parameter, which is either a `NextRequest` object (from `next/server`) or a standard web `Request` object.
|
||||
*/
|
||||
DataFlow::SourceNode getRequest() { result = this.getParameter(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A source of user-controlled data from a `NextRequest` object (from `next/server`) or a standard web `Request` object
|
||||
* in a Next.js App Router route handler.
|
||||
*/
|
||||
class NextAppRequestSource extends Http::RequestInputAccess {
|
||||
NextAppRouteHandler handler;
|
||||
string kind;
|
||||
|
||||
NextAppRequestSource() {
|
||||
(
|
||||
this =
|
||||
handler.getRequest().getAMethodCall(["json", "formData", "blob", "arrayBuffer", "text"])
|
||||
or
|
||||
this = handler.getRequest().getAPropertyRead("body")
|
||||
) and
|
||||
kind = "body"
|
||||
or
|
||||
this = handler.getRequest().getAPropertyRead(["url", "nextUrl"]) and
|
||||
kind = "url"
|
||||
or
|
||||
this =
|
||||
handler
|
||||
.getRequest()
|
||||
.getAPropertyRead("nextUrl")
|
||||
.getAPropertyRead("searchParams")
|
||||
.getAMemberCall("get") and
|
||||
kind = "parameter"
|
||||
or
|
||||
this = handler.getRequest().getAPropertyRead("headers") and kind = "headers"
|
||||
}
|
||||
|
||||
override string getKind() { result = kind }
|
||||
|
||||
override Http::RouteHandler getRouteHandler() { result = handler }
|
||||
|
||||
override string getSourceType() { result = "Next.js App Router request" }
|
||||
}
|
||||
}
|
||||
|
||||
103
javascript/ql/lib/semmle/javascript/frameworks/WebResponse.qll
Normal file
103
javascript/ql/lib/semmle/javascript/frameworks/WebResponse.qll
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Models the `Request` and `Response` objects from the Web standards.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
|
||||
/** Treats `Response` as an entry point for API graphs. */
|
||||
private class ResponseEntryPoint extends API::EntryPoint {
|
||||
ResponseEntryPoint() { this = "global.Response" }
|
||||
|
||||
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("Response") }
|
||||
}
|
||||
|
||||
/** Treats `Headers` as an entry point for API graphs. */
|
||||
private class HeadersEntryPoint extends API::EntryPoint {
|
||||
HeadersEntryPoint() { this = "global.Headers" }
|
||||
|
||||
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("Headers") }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `Response` and `NextResponse` constructor.
|
||||
*/
|
||||
private class ResponseCall extends API::InvokeNode {
|
||||
ResponseCall() {
|
||||
this = any(ResponseEntryPoint e).getANode().getAnInstantiation() or
|
||||
this = API::moduleImport("next/server").getMember("NextResponse").getAnInstantiation()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `Headers` constructor.
|
||||
*/
|
||||
private class HeadersCall extends API::InvokeNode {
|
||||
HeadersCall() { this = any(HeadersEntryPoint e).getANode().getAnInstantiation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `headers` in `new Response(body, { headers })`
|
||||
*/
|
||||
private class ResponseArgumentHeaders extends Http::HeaderDefinition {
|
||||
private ResponseCall response;
|
||||
private API::Node headerNode;
|
||||
|
||||
ResponseArgumentHeaders() {
|
||||
headerNode = response.getParameter(1).getMember("headers") and
|
||||
this = headerNode.asSink()
|
||||
}
|
||||
|
||||
ResponseCall getResponse() { result = response }
|
||||
|
||||
/**
|
||||
* Gets a call to `new Headers()` that is passed as the headers to this call.
|
||||
*/
|
||||
private HeadersCall getHeadersCall() { headerNode.refersTo(result.getReturn()) }
|
||||
|
||||
/**
|
||||
* Gets an object whose properties are interpreted as headers, such as `{'content-type': 'foo'}`.
|
||||
*/
|
||||
private API::Node getAPlainHeaderObject() {
|
||||
// new Response(body, {...})
|
||||
result = headerNode
|
||||
or
|
||||
// new Response(body, new Headers({...}))
|
||||
result = this.getHeadersCall().getParameter(0)
|
||||
}
|
||||
|
||||
private API::Node getHeaderNode(string headerName) {
|
||||
exists(string prop |
|
||||
result = this.getAPlainHeaderObject().getMember(prop) and
|
||||
headerName = prop.toLowerCase()
|
||||
)
|
||||
or
|
||||
exists(API::CallNode append |
|
||||
append = this.getHeadersCall().getReturn().getMember(["append", "set"]).getACall() and
|
||||
headerName = append.getArgument(0).getStringValue().toLowerCase() and
|
||||
result = append.getParameter(1)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate defines(string headerName, string headerValue) {
|
||||
this.getHeaderNode(headerName).getAValueReachingSink().getStringValue() = headerValue
|
||||
}
|
||||
|
||||
override string getAHeaderName() { exists(this.getHeaderNode(result)) }
|
||||
|
||||
override Http::RouteHandler getRouteHandler() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Data passed as the body in `new Response(body, ...)`.
|
||||
*/
|
||||
private class ResponseSink extends Http::ResponseSendArgument {
|
||||
private ResponseCall response;
|
||||
|
||||
ResponseSink() { this = response.getArgument(0) }
|
||||
|
||||
override Http::RouteHandler getRouteHandler() { none() }
|
||||
|
||||
override ResponseArgumentHeaders getAnAssociatedHeaderDefinition() {
|
||||
result.getResponse() = response
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,20 @@ private predicate areLibrariesCompatible(
|
||||
(client = LibraryNames::ws() or client = LibraryNames::websocket())
|
||||
}
|
||||
|
||||
/** Treats `WebSocket` as an entry point for API graphs. */
|
||||
private class WebSocketEntryPoint extends API::EntryPoint {
|
||||
WebSocketEntryPoint() { this = "global.WebSocket" }
|
||||
|
||||
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("WebSocket") }
|
||||
}
|
||||
|
||||
/** Treats `SockJS` as an entry point for API graphs. */
|
||||
private class SockJSEntryPoint extends API::EntryPoint {
|
||||
SockJSEntryPoint() { this = "global.SockJS" }
|
||||
|
||||
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("SockJS") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes that model WebSockets clients.
|
||||
*/
|
||||
@@ -56,7 +70,7 @@ module ClientWebSocket {
|
||||
/**
|
||||
* A class that can be used to instantiate a WebSocket instance.
|
||||
*/
|
||||
class SocketClass extends DataFlow::SourceNode {
|
||||
deprecated class SocketClass extends DataFlow::SourceNode {
|
||||
LibraryName library; // the name of the WebSocket library. Can be one of the libraries defined in `LibraryNames`.
|
||||
|
||||
SocketClass() {
|
||||
@@ -78,13 +92,38 @@ module ClientWebSocket {
|
||||
LibraryName getLibrary() { result = library }
|
||||
}
|
||||
|
||||
/**
|
||||
* A class that can be used to instantiate a WebSocket instance.
|
||||
*/
|
||||
class WebSocketClass extends API::Node {
|
||||
LibraryName library; // the name of the WebSocket library. Can be one of the libraries defined in `LibraryNames`.
|
||||
|
||||
WebSocketClass() {
|
||||
this = any(WebSocketEntryPoint e).getANode() and library = websocket()
|
||||
or
|
||||
this = API::moduleImport("ws") and library = ws()
|
||||
or
|
||||
// the sockjs-client library:https://www.npmjs.com/package/sockjs-client
|
||||
library = sockjs() and
|
||||
(
|
||||
this = API::moduleImport("sockjs-client") or
|
||||
this = any(SockJSEntryPoint e).getANode()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the WebSocket library name.
|
||||
*/
|
||||
LibraryName getLibrary() { result = library }
|
||||
}
|
||||
|
||||
/**
|
||||
* A client WebSocket instance.
|
||||
*/
|
||||
class ClientSocket extends EventEmitter::Range, DataFlow::NewNode, ClientRequest::Range {
|
||||
SocketClass socketClass;
|
||||
class ClientSocket extends EventEmitter::Range, API::NewNode, ClientRequest::Range {
|
||||
WebSocketClass socketClass;
|
||||
|
||||
ClientSocket() { this = socketClass.getAnInstantiation() }
|
||||
ClientSocket() { this = socketClass.getAnInvocation() }
|
||||
|
||||
/**
|
||||
* Gets the WebSocket library name.
|
||||
@@ -115,10 +154,10 @@ module ClientWebSocket {
|
||||
/**
|
||||
* A message sent from a WebSocket client.
|
||||
*/
|
||||
class SendNode extends EventDispatch::Range, DataFlow::CallNode {
|
||||
class SendNode extends EventDispatch::Range, API::CallNode {
|
||||
override ClientSocket emitter;
|
||||
|
||||
SendNode() { this = emitter.getAMemberCall("send") }
|
||||
SendNode() { this = emitter.getReturn().getMember("send").getACall() }
|
||||
|
||||
override string getChannel() { result = channelName() }
|
||||
|
||||
@@ -145,8 +184,8 @@ module ClientWebSocket {
|
||||
private DataFlow::FunctionNode getAMessageHandler(
|
||||
ClientWebSocket::ClientSocket emitter, string methodName
|
||||
) {
|
||||
exists(DataFlow::CallNode call |
|
||||
call = emitter.getAMemberCall(methodName) and
|
||||
exists(API::CallNode call |
|
||||
call = emitter.getReturn().getMember(methodName).getACall() and
|
||||
call.getArgument(0).mayHaveStringValue("message") and
|
||||
result = call.getCallback(1)
|
||||
)
|
||||
@@ -161,7 +200,13 @@ module ClientWebSocket {
|
||||
WebSocketReceiveNode() {
|
||||
this = getAMessageHandler(emitter, "addEventListener")
|
||||
or
|
||||
this = emitter.getAPropertyWrite("onmessage").getRhs()
|
||||
this = emitter.getReturn().getMember("onmessage").getAValueReachingSink()
|
||||
or
|
||||
exists(DataFlow::MethodCallNode bindCall |
|
||||
bindCall = emitter.getReturn().getMember("onmessage").getAValueReachingSink() and
|
||||
bindCall.getMethodName() = "bind" and
|
||||
this = bindCall.getReceiver().getAFunctionValue()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getReceivedItem(int i) {
|
||||
@@ -192,7 +237,7 @@ module ServerWebSocket {
|
||||
/**
|
||||
* Gets a server created by a library named `library`.
|
||||
*/
|
||||
DataFlow::SourceNode getAServer(LibraryName library) {
|
||||
deprecated DataFlow::SourceNode getAServer(LibraryName library) {
|
||||
library = ws() and
|
||||
result = DataFlow::moduleImport("ws").getAConstructorInvocation("Server")
|
||||
or
|
||||
@@ -200,11 +245,22 @@ module ServerWebSocket {
|
||||
result = DataFlow::moduleImport("sockjs").getAMemberCall("createServer")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a server created by a library named `library`.
|
||||
*/
|
||||
API::InvokeNode getAServerInvocation(LibraryName library) {
|
||||
library = ws() and
|
||||
result = API::moduleImport("ws").getMember("Server").getAnInvocation()
|
||||
or
|
||||
library = sockjs() and
|
||||
result = API::moduleImport("sockjs").getMember("createServer").getAnInvocation()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a `socket.on("connection", (msg, req) => {})` call.
|
||||
*/
|
||||
private DataFlow::CallNode getAConnectionCall(LibraryName library) {
|
||||
result = getAServer(library).getAMemberCall(EventEmitter::on()) and
|
||||
result = getAServerInvocation(library).getReturn().getMember(EventEmitter::on()).getACall() and
|
||||
result.getArgument(0).mayHaveStringValue("connection")
|
||||
}
|
||||
|
||||
@@ -324,15 +380,18 @@ module ServerWebSocket {
|
||||
result = this.getCallback(1).getParameter(0)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow node representing data received from a client, viewed as remote user input.
|
||||
*/
|
||||
private class ReceivedItemAsRemoteFlow extends RemoteFlowSource {
|
||||
ReceivedItemAsRemoteFlow() { this = any(ReceiveNode rercv).getReceivedItem(_) }
|
||||
|
||||
override string getSourceType() { result = "WebSocket client data" }
|
||||
|
||||
override predicate isUserControlledObject() { any() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow node representing data received from a client or server, viewed as remote user input.
|
||||
*/
|
||||
private class ReceivedItemAsRemoteFlow extends RemoteFlowSource {
|
||||
ReceivedItemAsRemoteFlow() {
|
||||
this = any(ClientWebSocket::ReceiveNode rercv).getReceivedItem(_) or
|
||||
this = any(ServerWebSocket::ReceiveNode rercv).getReceivedItem(_)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "WebSocket transmitted data" }
|
||||
|
||||
override predicate isUserControlledObject() { any() }
|
||||
}
|
||||
|
||||
@@ -12,3 +12,5 @@ private import Sets
|
||||
private import Strings
|
||||
private import DynamicImportStep
|
||||
private import UrlSearchParams
|
||||
private import TypedArrays
|
||||
private import Decoders
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
private import javascript
|
||||
private import semmle.javascript.dataflow.FlowSummary
|
||||
private import semmle.javascript.dataflow.InferredTypes
|
||||
private import semmle.javascript.dataflow.internal.DataFlowPrivate as Private
|
||||
private import FlowSummaryUtil
|
||||
|
||||
private class TextDecoderEntryPoint extends API::EntryPoint {
|
||||
TextDecoderEntryPoint() { this = "global.TextDecoder" }
|
||||
|
||||
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("TextDecoder") }
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
API::Node textDecoderConstructorRef() { result = any(TextDecoderEntryPoint e).getANode() }
|
||||
|
||||
class Decode extends SummarizedCallable {
|
||||
Decode() { this = "TextDecoder#decode" }
|
||||
|
||||
override InstanceCall getACall() {
|
||||
result = textDecoderConstructorRef().getInstance().getMember("decode").getACall()
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
preservesValue = false and
|
||||
input = "Argument[0].ArrayElement" and
|
||||
output = "ReturnValue"
|
||||
}
|
||||
}
|
||||
@@ -99,3 +99,19 @@ class StringSplitHashOrQuestionMark extends SummarizedCallable {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class StringFromCharCode extends SummarizedCallable {
|
||||
StringFromCharCode() { this = "String#fromCharCode" }
|
||||
|
||||
override DataFlow::CallNode getACall() {
|
||||
result = DataFlow::globalVarRef("String").getAPropertyRead("fromCharCode").getACall()
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
preservesValue = false and
|
||||
(
|
||||
input = "Argument[0..]" and
|
||||
output = "ReturnValue"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
private import javascript
|
||||
private import semmle.javascript.dataflow.FlowSummary
|
||||
private import semmle.javascript.dataflow.InferredTypes
|
||||
private import semmle.javascript.dataflow.internal.DataFlowPrivate as Private
|
||||
private import FlowSummaryUtil
|
||||
|
||||
private class TypedArrayEntryPoint extends API::EntryPoint {
|
||||
TypedArrayEntryPoint() { this = "global.Uint8Array" }
|
||||
|
||||
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("Uint8Array") }
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
API::Node typedArrayConstructorRef() { result = any(TypedArrayEntryPoint e).getANode() }
|
||||
|
||||
class TypedArrayConstructorSummary extends SummarizedCallable {
|
||||
TypedArrayConstructorSummary() { this = "TypedArray constructor" }
|
||||
|
||||
override DataFlow::InvokeNode getACall() {
|
||||
result = typedArrayConstructorRef().getAnInstantiation()
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
preservesValue = true and
|
||||
input = "Argument[0].ArrayElement" and
|
||||
output = "ReturnValue.ArrayElement"
|
||||
}
|
||||
}
|
||||
|
||||
class BufferTypedArray extends DataFlow::AdditionalFlowStep {
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(DataFlow::PropRead p |
|
||||
p = typedArrayConstructorRef().getInstance().getMember("buffer").asSource() and
|
||||
pred = p.getBase() and
|
||||
succ = p
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class TypedArraySet extends SummarizedCallable {
|
||||
TypedArraySet() { this = "TypedArray#set" }
|
||||
|
||||
override InstanceCall getACall() {
|
||||
result = typedArrayConstructorRef().getInstance().getMember("set").getACall()
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
preservesValue = true and
|
||||
input = "Argument[0].ArrayElement" and
|
||||
output = "Argument[this].ArrayElement"
|
||||
}
|
||||
}
|
||||
|
||||
class TypedArraySubarray extends SummarizedCallable {
|
||||
TypedArraySubarray() { this = "TypedArray#subarray" }
|
||||
|
||||
override InstanceCall getACall() { result.getMethodName() = "subarray" }
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
preservesValue = true and
|
||||
input = "Argument[this].ArrayElement" and
|
||||
output = "ReturnValue.ArrayElement"
|
||||
}
|
||||
}
|
||||
|
||||
private class ArrayBufferEntryPoint extends API::EntryPoint {
|
||||
ArrayBufferEntryPoint() { this = ["global.ArrayBuffer", "global.SharedArrayBuffer"] }
|
||||
|
||||
override DataFlow::SourceNode getASource() {
|
||||
result = DataFlow::globalVarRef(["ArrayBuffer", "SharedArrayBuffer"])
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
API::Node arrayBufferConstructorRef() { result = any(ArrayBufferEntryPoint a).getANode() }
|
||||
|
||||
class TransferLike extends SummarizedCallable {
|
||||
TransferLike() { this = "ArrayBuffer#transfer" }
|
||||
|
||||
override InstanceCall getACall() {
|
||||
result.getMethodName() = ["transfer", "transferToFixedLength"]
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
preservesValue = true and
|
||||
input = "Argument[this].ArrayElement" and
|
||||
output = "ReturnValue.ArrayElement"
|
||||
}
|
||||
}
|
||||
@@ -32,11 +32,11 @@ module ReflectedXss {
|
||||
* Gets a HeaderDefinition that defines a XSS safe content-type for `send`.
|
||||
*/
|
||||
Http::HeaderDefinition getAXssSafeHeaderDefinition(Http::ResponseSendArgument send) {
|
||||
exists(Http::RouteHandler h |
|
||||
send.getRouteHandler() = h and
|
||||
result = xssSafeContentTypeHeader(h)
|
||||
|
|
||||
// The HeaderDefinition affects a response sent at `send`.
|
||||
isSafeContentTypeHeader(result) and
|
||||
(
|
||||
result = send.getAnAssociatedHeaderDefinition()
|
||||
or
|
||||
result = send.getRouteHandler().getAResponseHeader("content-type") and
|
||||
headerAffects(result, send)
|
||||
)
|
||||
}
|
||||
@@ -54,16 +54,22 @@ module ReflectedXss {
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `h` may send a response with a content type that is safe for XSS.
|
||||
*/
|
||||
Http::HeaderDefinition xssSafeContentTypeHeader(Http::RouteHandler h) {
|
||||
result = h.getAResponseHeader("content-type") and
|
||||
not exists(string tp | result.defines("content-type", tp) |
|
||||
private predicate isSafeContentTypeHeader(Http::HeaderDefinition header) {
|
||||
header.getAHeaderName() = "content-type" and
|
||||
not exists(string tp | header.defines("content-type", tp) |
|
||||
tp.toLowerCase().matches(xssUnsafeContentType() + "%")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use `getAXssSafeHeaderDefinition` instead.
|
||||
* Holds if `h` may send a response with a content type that is safe for XSS.
|
||||
*/
|
||||
deprecated Http::HeaderDefinition xssSafeContentTypeHeader(Http::RouteHandler h) {
|
||||
result = h.getAResponseHeader("content-type") and
|
||||
isSafeContentTypeHeader(result)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a header set in `header` is likely to affect a response sent at `sender`.
|
||||
*/
|
||||
@@ -80,6 +86,8 @@ module ReflectedXss {
|
||||
dominatingHeader.getBasicBlock().(ReachableBasicBlock).dominates(sender.getBasicBlock())
|
||||
)
|
||||
)
|
||||
or
|
||||
header = sender.getAnAssociatedHeaderDefinition()
|
||||
}
|
||||
|
||||
bindingset[headerBlock]
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
## 1.5.3
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Data passed to the [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) constructor is now treated as a sink for `js/reflected-xss`.
|
||||
* Slightly improved detection of DOM element references, leading to XSS results being detected in more cases.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fixed a bug that would prevent extraction of `tsconfig.json` files when it contained an array literal with a trailing comma.
|
||||
|
||||
## 1.5.2
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id js/useless-expression
|
||||
* @tags maintainability
|
||||
* @tags quality
|
||||
* maintainability
|
||||
* correctness
|
||||
* external/cwe/cwe-480
|
||||
* external/cwe/cwe-561
|
||||
* useless-code
|
||||
* @precision very-high
|
||||
*/
|
||||
|
||||
|
||||
@@ -30,30 +30,26 @@ private int powerOfTwo() {
|
||||
* Gets a node that has value 2^n for some n.
|
||||
*/
|
||||
private DataFlow::Node isPowerOfTwo() {
|
||||
exists(DataFlow::Node prev |
|
||||
prev.getIntValue() = powerOfTwo()
|
||||
or
|
||||
// Getting around the 32 bit ints in QL. These are some hex values of the form 0x10000000
|
||||
prev.asExpr().(NumberLiteral).getValue() =
|
||||
["281474976710656", "17592186044416", "1099511627776", "68719476736", "4294967296"]
|
||||
|
|
||||
result = prev.getASuccessor*()
|
||||
)
|
||||
result.getIntValue() = powerOfTwo()
|
||||
or
|
||||
// Getting around the 32 bit ints in QL. These are some hex values of the form 0x10000000
|
||||
result.asExpr().(NumberLiteral).getValue() =
|
||||
["281474976710656", "17592186044416", "1099511627776", "68719476736", "4294967296"]
|
||||
or
|
||||
result = isPowerOfTwo().getASuccessor()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node that has value (2^n)-1 for some n.
|
||||
*/
|
||||
private DataFlow::Node isPowerOfTwoMinusOne() {
|
||||
exists(DataFlow::Node prev |
|
||||
prev.getIntValue() = powerOfTwo() - 1
|
||||
or
|
||||
// Getting around the 32 bit ints in QL. These are some hex values of the form 0xfffffff
|
||||
prev.asExpr().(NumberLiteral).getValue() =
|
||||
["281474976710655", "17592186044415", "1099511627775", "68719476735", "4294967295"]
|
||||
|
|
||||
result = prev.getASuccessor*()
|
||||
)
|
||||
result.getIntValue() = powerOfTwo() - 1
|
||||
or
|
||||
// Getting around the 32 bit ints in QL. These are some hex values of the form 0xfffffff
|
||||
result.asExpr().(NumberLiteral).getValue() =
|
||||
["281474976710655", "17592186044415", "1099511627775", "68719476735", "4294967295"]
|
||||
or
|
||||
result = isPowerOfTwoMinusOne().getASuccessor()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
10
javascript/ql/src/Security/trest/test.ql
Normal file
10
javascript/ql/src/Security/trest/test.ql
Normal file
@@ -0,0 +1,10 @@
|
||||
import javascript
|
||||
|
||||
API::NewNode getAWebSocketInstance() { result instanceof ClientWebSocket::ClientSocket }
|
||||
|
||||
from DataFlow::Node handler
|
||||
where
|
||||
handler = getAWebSocketInstance().getReturn().getMember("onmessage").asSource()
|
||||
or
|
||||
handler = getAWebSocketInstance().getAPropertyWrite("onmessage").getRhs()
|
||||
select handler, "This is a WebSocket onmessage handler."
|
||||
10
javascript/ql/src/change-notes/released/1.5.3.md
Normal file
10
javascript/ql/src/change-notes/released/1.5.3.md
Normal file
@@ -0,0 +1,10 @@
|
||||
## 1.5.3
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Data passed to the [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) constructor is now treated as a sink for `js/reflected-xss`.
|
||||
* Slightly improved detection of DOM element references, leading to XSS results being detected in more cases.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fixed a bug that would prevent extraction of `tsconfig.json` files when it contained an array literal with a trailing comma.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.5.2
|
||||
lastReleaseVersion: 1.5.3
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/javascript-queries
|
||||
version: 1.5.2
|
||||
version: 1.5.3
|
||||
groups:
|
||||
- javascript
|
||||
- queries
|
||||
|
||||
@@ -9,3 +9,21 @@ function f() {
|
||||
lib.m1({
|
||||
...f()
|
||||
})
|
||||
|
||||
function getArgs() {
|
||||
return [
|
||||
'x', /* def=moduleImport("something").getMember("exports").getMember("m2").getSpreadArgument(0).getArrayElement() */
|
||||
'y', /* def=moduleImport("something").getMember("exports").getMember("m2").getSpreadArgument(0).getArrayElement() */
|
||||
]
|
||||
}
|
||||
|
||||
lib.m2(...getArgs());
|
||||
|
||||
function f3() {
|
||||
return [
|
||||
'x', /* def=moduleImport("something").getMember("exports").getMember("m3").getSpreadArgument(1).getArrayElement() */
|
||||
'y', /* def=moduleImport("something").getMember("exports").getMember("m3").getSpreadArgument(1).getArrayElement() */
|
||||
]
|
||||
}
|
||||
|
||||
lib.m3.bind(undefined, 1)(...f3());
|
||||
|
||||
@@ -7,20 +7,26 @@ test_documentRef
|
||||
test_locationRef
|
||||
| customization.js:3:3:3:14 | doc.location |
|
||||
test_domValueRef
|
||||
| customization.js:2:13:2:31 | customGetDocument() |
|
||||
| customization.js:3:3:3:14 | doc.location |
|
||||
| customization.js:4:3:4:20 | doc.getElementById |
|
||||
| customization.js:4:3:4:28 | doc.get ... 'test') |
|
||||
| event-handler-receiver.html:4:20:4:19 | this |
|
||||
| event-handler-receiver.js:1:1:1:8 | document |
|
||||
| event-handler-receiver.js:1:1:1:23 | documen ... entById |
|
||||
| event-handler-receiver.js:1:1:1:32 | documen ... my-id') |
|
||||
| event-handler-receiver.js:1:44:1:43 | this |
|
||||
| event-handler-receiver.js:2:3:2:17 | this.parentNode |
|
||||
| event-handler-receiver.js:5:1:5:8 | document |
|
||||
| event-handler-receiver.js:5:1:5:23 | documen ... entById |
|
||||
| event-handler-receiver.js:5:1:5:32 | documen ... my-id') |
|
||||
| event-handler-receiver.js:5:60:5:59 | this |
|
||||
| event-handler-receiver.js:6:3:6:17 | this.parentNode |
|
||||
| nameditems.js:1:1:1:8 | document |
|
||||
| nameditems.js:1:1:1:23 | documen ... entById |
|
||||
| nameditems.js:1:1:1:30 | documen ... ('foo') |
|
||||
| nameditems.js:1:1:2:19 | documen ... em('x') |
|
||||
| querySelectorAll.js:2:5:2:12 | document |
|
||||
| querySelectorAll.js:2:5:2:29 | documen ... ctorAll |
|
||||
| querySelectorAll.js:2:5:2:36 | documen ... ('foo') |
|
||||
| querySelectorAll.js:2:46:2:48 | elm |
|
||||
|
||||
@@ -31,14 +31,14 @@ sensitiveAction
|
||||
| tst.js:23:1:23:25 | require ... .exit() |
|
||||
| tst.js:24:1:24:21 | global. ... .exit() |
|
||||
sensitiveExpr
|
||||
| tst.js:1:1:1:8 | password |
|
||||
| tst.js:2:1:2:8 | PassWord |
|
||||
| tst.js:3:1:3:21 | myPassw ... eartext |
|
||||
| tst.js:4:1:4:10 | x.password |
|
||||
| tst.js:5:1:5:11 | getPassword |
|
||||
| tst.js:5:1:5:13 | getPassword() |
|
||||
| tst.js:6:1:6:13 | x.getPassword |
|
||||
| tst.js:6:1:6:15 | x.getPassword() |
|
||||
| tst.js:7:1:7:15 | get("password") |
|
||||
| tst.js:8:1:8:17 | x.get("password") |
|
||||
| tst.js:21:1:21:6 | secret |
|
||||
| tst.js:1:1:1:8 | password | password |
|
||||
| tst.js:2:1:2:8 | PassWord | password |
|
||||
| tst.js:3:1:3:21 | myPassw ... eartext | password |
|
||||
| tst.js:4:1:4:10 | x.password | password |
|
||||
| tst.js:5:1:5:11 | getPassword | password |
|
||||
| tst.js:5:1:5:13 | getPassword() | password |
|
||||
| tst.js:6:1:6:13 | x.getPassword | password |
|
||||
| tst.js:6:1:6:15 | x.getPassword() | password |
|
||||
| tst.js:7:1:7:15 | get("password") | password |
|
||||
| tst.js:8:1:8:17 | x.get("password") | password |
|
||||
| tst.js:21:1:21:6 | secret | secret |
|
||||
|
||||
@@ -20,4 +20,4 @@ query predicate processTermination(NodeJSLib::ProcessTermination term) { any() }
|
||||
|
||||
query predicate sensitiveAction(SensitiveAction ac) { any() }
|
||||
|
||||
query predicate sensitiveExpr(SensitiveNode e) { any() }
|
||||
query predicate sensitiveExpr(SensitiveNode e, string kind) { kind = e.getClassification() }
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
query: tests.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
@@ -1,11 +1,11 @@
|
||||
password;
|
||||
PassWord;
|
||||
myPasswordInCleartext;
|
||||
x.password;
|
||||
getPassword();
|
||||
x.getPassword();
|
||||
get("password");
|
||||
x.get("password");
|
||||
password; // $ cleartextPasswordExpr sensitiveExpr=password
|
||||
PassWord; // $ cleartextPasswordExpr sensitiveExpr=password
|
||||
myPasswordInCleartext; // $ cleartextPasswordExpr sensitiveExpr=password
|
||||
x.password; // $ cleartextPasswordExpr sensitiveExpr=password
|
||||
getPassword(); // $ cleartextPasswordExpr sensitiveExpr=password
|
||||
x.getPassword(); // $ cleartextPasswordExpr sensitiveExpr=password
|
||||
get("password"); // $ cleartextPasswordExpr sensitiveExpr=password
|
||||
x.get("password"); // $ cleartextPasswordExpr sensitiveExpr=password
|
||||
|
||||
hashed_password;
|
||||
password_hashed;
|
||||
@@ -15,13 +15,13 @@ hashedPassword;
|
||||
|
||||
var exit = require('exit');
|
||||
var e = process.exit;
|
||||
e();
|
||||
exit();
|
||||
e(); // $ processTermination sensitiveAction
|
||||
exit(); // $ processTermination sensitiveAction
|
||||
|
||||
secret;
|
||||
secret; // $ sensitiveExpr=secret
|
||||
|
||||
require("process").exit();
|
||||
global.process.exit();
|
||||
require("process").exit(); // $ processTermination sensitiveAction
|
||||
global.process.exit(); // $ processTermination sensitiveAction
|
||||
|
||||
get("https://example.com/news?password=true")
|
||||
get("https://username:password@example.com")
|
||||
|
||||
@@ -35,11 +35,23 @@ legacyDataFlowDifference
|
||||
| spread.js:4:15:4:22 | source() | spread.js:18:8:18:8 | y | only flow with NEW data flow library |
|
||||
| spread.js:4:15:4:22 | source() | spread.js:24:8:24:8 | y | only flow with NEW data flow library |
|
||||
| tst.js:2:13:2:20 | source() | tst.js:17:10:17:10 | a | only flow with OLD data flow library |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:5:10:5:10 | y | only flow with NEW data flow library |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:7:10:7:17 | y.buffer | only flow with NEW data flow library |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:11:10:11:12 | arr | only flow with NEW data flow library |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:15:10:15:10 | z | only flow with NEW data flow library |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:18:10:18:12 | sub | only flow with NEW data flow library |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:42:10:42:30 | typedAr ... ring(y) | only flow with NEW data flow library |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:48:10:48:12 | str | only flow with NEW data flow library |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:52:10:52:13 | str2 | only flow with NEW data flow library |
|
||||
| use-use-after-implicit-read.js:7:17:7:24 | source() | use-use-after-implicit-read.js:15:10:15:10 | x | only flow with NEW data flow library |
|
||||
consistencyIssue
|
||||
| nested-props.js:20 | expected an alert, but found none | NOT OK - but not found | Consistency |
|
||||
| stringification-read-steps.js:17 | expected an alert, but found none | NOT OK | Consistency |
|
||||
| stringification-read-steps.js:25 | expected an alert, but found none | NOT OK | Consistency |
|
||||
| typed-arrays.js:23 | expected an alert, but found none | NOT OK -- Should be flagged but it is not. | Consistency |
|
||||
| typed-arrays.js:28 | expected an alert, but found none | NOT OK -- Should be flagged but it is not. | Consistency |
|
||||
| typed-arrays.js:32 | expected an alert, but found none | NOT OK -- Should be flagged but it is not. | Consistency |
|
||||
| typed-arrays.js:36 | expected an alert, but found none | NOT OK -- Should be flagged but it is not. | Consistency |
|
||||
flow
|
||||
| access-path-sanitizer.js:2:18:2:25 | source() | access-path-sanitizer.js:4:8:4:12 | obj.x |
|
||||
| addexpr.js:4:10:4:17 | source() | addexpr.js:7:8:7:8 | x |
|
||||
@@ -325,6 +337,14 @@ flow
|
||||
| tst.js:87:22:87:29 | source() | tst.js:90:14:90:25 | taintedValue |
|
||||
| tst.js:93:22:93:29 | source() | tst.js:96:14:96:25 | taintedValue |
|
||||
| tst.js:93:22:93:29 | source() | tst.js:97:14:97:26 | map.get(true) |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:5:10:5:10 | y |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:7:10:7:17 | y.buffer |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:11:10:11:12 | arr |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:15:10:15:10 | z |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:18:10:18:12 | sub |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:42:10:42:30 | typedAr ... ring(y) |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:48:10:48:12 | str |
|
||||
| typed-arrays.js:2:13:2:20 | source() | typed-arrays.js:52:10:52:13 | str2 |
|
||||
| use-use-after-implicit-read.js:7:17:7:24 | source() | use-use-after-implicit-read.js:8:10:8:17 | captured |
|
||||
| use-use-after-implicit-read.js:7:17:7:24 | source() | use-use-after-implicit-read.js:15:10:15:10 | x |
|
||||
| xml.js:5:18:5:25 | source() | xml.js:8:14:8:17 | text |
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
function test() {
|
||||
let x = source();
|
||||
|
||||
let y = new Uint8Array(x);
|
||||
sink(y); // NOT OK
|
||||
|
||||
sink(y.buffer); // NOT OK
|
||||
sink(y.length);
|
||||
|
||||
var arr = new Uint8Array(y.buffer, y.byteOffset, y.byteLength);
|
||||
sink(arr); // NOT OK
|
||||
|
||||
const z = new Uint8Array([1, 2, 3]);
|
||||
z.set(y, 3);
|
||||
sink(z); // NOT OK
|
||||
|
||||
const sub = y.subarray(1, 3)
|
||||
sink(sub); // NOT OK
|
||||
|
||||
const buffer = new ArrayBuffer(8);
|
||||
const view = new Uint8Array(buffer);
|
||||
view.set(x, 3);
|
||||
sink(buffer); // NOT OK -- Should be flagged but it is not.
|
||||
|
||||
const sharedBuffer = new SharedArrayBuffer(8);
|
||||
const view1 = new Uint8Array(sharedBuffer);
|
||||
view1.set(x, 3);
|
||||
sink(sharedBuffer); // NOT OK -- Should be flagged but it is not.
|
||||
|
||||
const transfered = buffer.transfer();
|
||||
const transferedView = new Uint8Array(transfered);
|
||||
sink(transferedView); // NOT OK -- Should be flagged but it is not.
|
||||
|
||||
const transfered2 = buffer.transferToFixedLength();
|
||||
const transferedView2 = new Uint8Array(transfered2);
|
||||
sink(transferedView2); // NOT OK -- Should be flagged but it is not.
|
||||
|
||||
var typedArrayToString = (function () {
|
||||
return function (a) { return String.fromCharCode.apply(null, a); };
|
||||
})();
|
||||
|
||||
sink(typedArrayToString(y)); // NOT OK
|
||||
|
||||
let str = '';
|
||||
for (let i = 0; i < y.length; i++)
|
||||
str += String.fromCharCode(y[i]);
|
||||
|
||||
sink(str); // NOT OK
|
||||
|
||||
const decoder = new TextDecoder('utf-8');
|
||||
const str2 = decoder.decode(y);
|
||||
sink(str2); // NOT OK
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import { MyWebSocket, MySockJS, myWebSocketInstance, mySockJSInstance } from './browser.js';
|
||||
|
||||
(function () {
|
||||
const socket = new MyWebSocket('ws://localhost:9080'); // $ clientSocket
|
||||
|
||||
socket.addEventListener('open', function (event) {
|
||||
socket.send('Hi from browser!'); // $ clientSend
|
||||
});
|
||||
|
||||
socket.addEventListener('message', function (event) {
|
||||
console.log('Message from server ', event.data); // $ remoteFlow
|
||||
}); // $ clientReceive
|
||||
|
||||
socket.onmessage = function (event) {
|
||||
console.log("Message from server 2", event.data); // $ remoteFlow
|
||||
}; // $ clientReceive
|
||||
})();
|
||||
|
||||
|
||||
(function () {
|
||||
var sock = new MySockJS('http://0.0.0.0:9999/echo'); // $ clientSocket
|
||||
sock.onopen = function () {
|
||||
sock.send('test'); // $ clientSend
|
||||
};
|
||||
|
||||
sock.onmessage = function (e) {
|
||||
console.log('message', e.data); // $ remoteFlow
|
||||
sock.close();
|
||||
}; // $ clientReceive
|
||||
|
||||
sock.addEventListener('message', function (event) {
|
||||
console.log('Using addEventListener ', event.data); // $ remoteFlow
|
||||
}); // $ clientReceive
|
||||
})();
|
||||
|
||||
|
||||
(function () {
|
||||
myWebSocketInstance.addEventListener('open', function (event) {
|
||||
myWebSocketInstance.send('Hi from browser!'); // $ clientSend
|
||||
});
|
||||
|
||||
myWebSocketInstance.addEventListener('message', function (event) {
|
||||
console.log('Message from server ', event.data); // $ remoteFlow
|
||||
}); // $ clientReceive
|
||||
|
||||
myWebSocketInstance.onmessage = function (event) {
|
||||
console.log("Message from server 2", event.data); // $ remoteFlow
|
||||
}; // $ clientReceive
|
||||
})();
|
||||
|
||||
|
||||
(function () {
|
||||
mySockJSInstance.onopen = function () {
|
||||
mySockJSInstance.send('test'); // $ clientSend
|
||||
};
|
||||
|
||||
mySockJSInstance.onmessage = function (e) {
|
||||
console.log('message', e.data); // $ remoteFlow
|
||||
mySockJSInstance.close();
|
||||
}; // $ clientReceive
|
||||
|
||||
mySockJSInstance.addEventListener('message', function (event) {
|
||||
console.log('Using addEventListener ', event.data); // $ remoteFlow
|
||||
}); // $ clientReceive
|
||||
})();
|
||||
|
||||
|
||||
const recv_message = function (e) {
|
||||
console.log('Received message:', e.data); // $ remoteFlow
|
||||
}; // $ clientReceive
|
||||
|
||||
(function () {
|
||||
myWebSocketInstance.onmessage = recv_message.bind(this);
|
||||
})();
|
||||
@@ -1,32 +1,37 @@
|
||||
(function () {
|
||||
const socket = new WebSocket('ws://localhost:8080');
|
||||
const socket = new WebSocket('ws://localhost:8080'); // $clientSocket
|
||||
|
||||
socket.addEventListener('open', function (event) {
|
||||
socket.send('Hi from browser!');
|
||||
socket.send('Hi from browser!'); // $clientSend
|
||||
});
|
||||
|
||||
socket.addEventListener('message', function (event) {
|
||||
console.log('Message from server ', event.data);
|
||||
});
|
||||
console.log('Message from server ', event.data); // $ remoteFlow
|
||||
}); // $clientReceive
|
||||
|
||||
socket.onmessage = function (event) {
|
||||
console.log("Message from server 2", event.data)
|
||||
};
|
||||
console.log("Message from server 2", event.data); // $ remoteFlow
|
||||
}; // $clientReceive
|
||||
})();
|
||||
|
||||
|
||||
(function () {
|
||||
var sock = new SockJS('http://0.0.0.0:9999/echo');
|
||||
var sock = new SockJS('http://0.0.0.0:9999/echo'); // $clientSocket
|
||||
sock.onopen = function () {
|
||||
sock.send('test');
|
||||
sock.send('test'); // $clientSend
|
||||
};
|
||||
|
||||
sock.onmessage = function (e) {
|
||||
console.log('message', e.data);
|
||||
console.log('message', e.data); // $ remoteFlow
|
||||
sock.close();
|
||||
};
|
||||
}; // $clientReceive
|
||||
|
||||
sock.addEventListener('message', function (event) {
|
||||
console.log('Using addEventListener ', event.data);
|
||||
});
|
||||
})
|
||||
console.log('Using addEventListener ', event.data); // $ remoteFlow
|
||||
}); // $clientReceive
|
||||
})();
|
||||
|
||||
export const MyWebSocket = WebSocket;
|
||||
export const MySockJS = SockJS;
|
||||
export const myWebSocketInstance = new WebSocket('ws://localhost:8080'); // $ clientSocket
|
||||
export const mySockJSInstance = new SockJS('http://0.0.0.0:9999/echo'); // $ clientSocket
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
const { MyWebSocketWS, myWebSocketWSInstance } = require('./client.js');
|
||||
|
||||
(function () {
|
||||
const ws = new MyWebSocketWS('ws://example.org'); // $ clientSocket
|
||||
|
||||
ws.on('open', function open() {
|
||||
ws.send('Hi from client!'); // $ clientSend
|
||||
});
|
||||
|
||||
ws.on('message', function incoming(data) { // $ remoteFlow
|
||||
console.log(data);
|
||||
}); // $ clientReceive
|
||||
})();
|
||||
|
||||
(function () {
|
||||
myWebSocketWSInstance.on('open', function open() {
|
||||
myWebSocketWSInstance.send('Hi from client!'); // $ clientSend
|
||||
});
|
||||
|
||||
myWebSocketWSInstance.on('message', function incoming(data) { // $ remoteFlow
|
||||
console.log(data);
|
||||
}); // $ clientReceive
|
||||
})();
|
||||
@@ -1,13 +1,16 @@
|
||||
(function () {
|
||||
const WebSocket = require('ws');
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const ws = new WebSocket('ws://example.org');
|
||||
(function () {
|
||||
const ws = new WebSocket('ws://example.org'); // $clientSocket
|
||||
|
||||
ws.on('open', function open() {
|
||||
ws.send('Hi from client!');
|
||||
ws.send('Hi from client!'); // $clientSend
|
||||
});
|
||||
|
||||
ws.on('message', function incoming(data) {
|
||||
ws.on('message', function incoming(data) { // $ remoteFlow
|
||||
console.log(data);
|
||||
});
|
||||
})();
|
||||
}); // $clientReceive
|
||||
})();
|
||||
|
||||
module.exports.MyWebSocketWS = require('ws');
|
||||
module.exports.myWebSocketWSInstance = new WebSocket('ws://example.org'); // $ clientSocket
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
const { MyWebSocketServer, myWebSocketServerInstance } = require('./server.js');
|
||||
|
||||
(function () {
|
||||
const wss = new MyWebSocketServer({ port: 8080 });
|
||||
|
||||
wss.on('connection', function connection(ws) { // $ serverSocket
|
||||
ws.on('message', function incoming(message) { // $ remoteFlow
|
||||
console.log('received: %s', message);
|
||||
}); // $ serverReceive
|
||||
|
||||
ws.send('Hi from server!'); // $ serverSend
|
||||
});
|
||||
})();
|
||||
|
||||
(function () {
|
||||
myWebSocketServerInstance.on('connection', function connection(ws) { // $ serverSocket
|
||||
ws.on('message', function incoming(message) { // $ remoteFlow
|
||||
console.log('received: %s', message);
|
||||
}); // $ serverReceive
|
||||
|
||||
ws.send('Hi from server!'); // $ serverSend
|
||||
});
|
||||
})();
|
||||
@@ -1,13 +1,16 @@
|
||||
(function () {
|
||||
const WebSocket = require('ws');
|
||||
const WebSocket = require('ws');
|
||||
|
||||
(function () {
|
||||
const wss = new WebSocket.Server({ port: 8080 });
|
||||
|
||||
wss.on('connection', function connection(ws) {
|
||||
ws.on('message', function incoming(message) {
|
||||
wss.on('connection', function connection(ws) { // $serverSocket
|
||||
ws.on('message', function incoming(message) { // $remoteFlow
|
||||
console.log('received: %s', message);
|
||||
});
|
||||
}); // $serverReceive
|
||||
|
||||
ws.send('Hi from server!');
|
||||
ws.send('Hi from server!'); // $serverSend
|
||||
});
|
||||
})();
|
||||
})();
|
||||
|
||||
module.exports.MyWebSocketServer = require('ws').Server;
|
||||
module.exports.myWebSocketServerInstance = new WebSocket.Server({ port: 8080 });
|
||||
|
||||
@@ -5,11 +5,11 @@ const sockjs = require('sockjs');
|
||||
const app = express();
|
||||
const server = http.createServer(app);
|
||||
const sockjs_echo = sockjs.createServer({});
|
||||
sockjs_echo.on('connection', function (conn) {
|
||||
conn.on('data', function (message) {
|
||||
sockjs_echo.on('connection', function (conn) { // $serverSocket
|
||||
conn.on('data', function (message) { // $remoteFlow
|
||||
var data = JSON.parse(message);
|
||||
conn.write(JSON.stringify(eval(data.test)));
|
||||
});
|
||||
conn.write(JSON.stringify(eval(data.test))); // $serverSend
|
||||
}); // $serverReceive
|
||||
});
|
||||
|
||||
sockjs_echo.installHandlers(server, { prefix: '/echo' });
|
||||
|
||||
@@ -1,35 +1,139 @@
|
||||
clientSocket
|
||||
| browser.js:2:17:2:52 | new Web ... :8080') |
|
||||
| browser.js:19:13:19:50 | new Soc ... /echo') |
|
||||
| client.js:4:13:4:45 | new Web ... e.org') |
|
||||
clientReceive
|
||||
| browser-custom.js:10:37:12:2 | functio ... Flow\\n\\t} |
|
||||
| browser-custom.js:14:21:16:2 | functio ... Flow\\n\\t} |
|
||||
| browser-custom.js:26:19:29:2 | functio ... e();\\n\\t} |
|
||||
| browser-custom.js:31:35:33:2 | functio ... Flow\\n\\t} |
|
||||
| browser-custom.js:42:53:44:5 | functio ... w\\n } |
|
||||
| browser-custom.js:46:37:48:5 | functio ... w\\n } |
|
||||
| browser-custom.js:57:34:60:5 | functio ... ;\\n } |
|
||||
| browser-custom.js:62:50:64:5 | functio ... w\\n } |
|
||||
| browser-custom.js:68:22:70:1 | functio ... eFlow\\n} |
|
||||
| browser.js:8:37:10:2 | functio ... Flow\\n\\t} |
|
||||
| browser.js:12:21:14:2 | functio ... Flow\\n\\t} |
|
||||
| browser.js:24:19:27:2 | functio ... e();\\n\\t} |
|
||||
| browser.js:29:35:31:2 | functio ... Flow\\n\\t} |
|
||||
| client-custom.js:10:19:12:2 | functio ... ta);\\n\\t} |
|
||||
| client-custom.js:20:38:22:2 | functio ... ta);\\n\\t} |
|
||||
| client.js:10:19:12:2 | functio ... ta);\\n\\t} |
|
||||
clientSend
|
||||
| browser-custom.js:7:3:7:33 | socket. ... wser!') |
|
||||
| browser-custom.js:23:3:23:19 | sock.send('test') |
|
||||
| browser-custom.js:39:9:39:52 | myWebSo ... wser!') |
|
||||
| browser-custom.js:54:9:54:37 | mySockJ ... 'test') |
|
||||
| browser.js:5:3:5:33 | socket. ... wser!') |
|
||||
| browser.js:21:3:21:19 | sock.send('test') |
|
||||
| client-custom.js:7:3:7:28 | ws.send ... ient!') |
|
||||
| client-custom.js:17:3:17:47 | myWebSo ... ient!') |
|
||||
| client.js:7:3:7:28 | ws.send ... ient!') |
|
||||
clientReceive
|
||||
| browser.js:8:37:10:2 | functio ... ta);\\n\\t} |
|
||||
| browser.js:12:21:14:2 | functio ... ata)\\n\\t} |
|
||||
| browser.js:24:19:27:2 | functio ... e();\\n\\t} |
|
||||
| browser.js:29:35:31:2 | functio ... ta);\\n\\t} |
|
||||
| client.js:10:19:12:2 | functio ... ta);\\n\\t} |
|
||||
serverSocket
|
||||
| server.js:6:43:6:44 | ws |
|
||||
| sockjs.js:8:40:8:43 | conn |
|
||||
serverSend
|
||||
| server.js:11:3:11:28 | ws.send ... rver!') |
|
||||
| sockjs.js:11:9:11:51 | conn.wr ... test))) |
|
||||
serverReceive
|
||||
| server.js:7:3:9:4 | ws.on(' ... );\\n\\t\\t}) |
|
||||
| sockjs.js:9:5:12:6 | conn.on ... \\n }) |
|
||||
clientSocket
|
||||
| browser-custom.js:4:17:4:54 | new MyW ... :9080') |
|
||||
| browser-custom.js:21:13:21:52 | new MyS ... /echo') |
|
||||
| browser.js:2:17:2:52 | new Web ... :8080') |
|
||||
| browser.js:19:13:19:50 | new Soc ... /echo') |
|
||||
| browser.js:36:36:36:71 | new Web ... :8080') |
|
||||
| browser.js:37:33:37:70 | new Soc ... /echo') |
|
||||
| client-custom.js:4:13:4:49 | new MyW ... e.org') |
|
||||
| client.js:4:13:4:45 | new Web ... e.org') |
|
||||
| client.js:16:40:16:72 | new Web ... e.org') |
|
||||
flowSteps
|
||||
| browser-custom.js:1:10:1:20 | MyWebSocket | browser-custom.js:1:10:1:20 | MyWebSocket |
|
||||
| browser-custom.js:1:23:1:30 | MySockJS | browser-custom.js:1:23:1:30 | MySockJS |
|
||||
| browser-custom.js:1:33:1:51 | myWebSocketInstance | browser-custom.js:1:33:1:51 | myWebSocketInstance |
|
||||
| browser-custom.js:1:54:1:69 | mySockJSInstance | browser-custom.js:1:54:1:69 | mySockJSInstance |
|
||||
| browser-custom.js:7:15:7:32 | 'Hi from browser!' | server-custom.js:7:38:7:44 | message |
|
||||
| browser-custom.js:7:15:7:32 | 'Hi from browser!' | server-custom.js:17:38:17:44 | message |
|
||||
| browser-custom.js:7:15:7:32 | 'Hi from browser!' | server.js:7:38:7:44 | message |
|
||||
| browser-custom.js:23:13:23:18 | 'test' | sockjs.js:9:31:9:37 | message |
|
||||
| browser-custom.js:39:34:39:51 | 'Hi from browser!' | server-custom.js:7:38:7:44 | message |
|
||||
| browser-custom.js:39:34:39:51 | 'Hi from browser!' | server-custom.js:17:38:17:44 | message |
|
||||
| browser-custom.js:39:34:39:51 | 'Hi from browser!' | server.js:7:38:7:44 | message |
|
||||
| browser-custom.js:54:31:54:36 | 'test' | sockjs.js:9:31:9:37 | message |
|
||||
| browser.js:5:15:5:32 | 'Hi from browser!' | server-custom.js:7:38:7:44 | message |
|
||||
| browser.js:5:15:5:32 | 'Hi from browser!' | server-custom.js:17:38:17:44 | message |
|
||||
| browser.js:5:15:5:32 | 'Hi from browser!' | server.js:7:38:7:44 | message |
|
||||
| browser.js:21:13:21:18 | 'test' | sockjs.js:9:31:9:37 | message |
|
||||
| client-custom.js:7:11:7:27 | 'Hi from client!' | server-custom.js:7:38:7:44 | message |
|
||||
| client-custom.js:7:11:7:27 | 'Hi from client!' | server-custom.js:17:38:17:44 | message |
|
||||
| client-custom.js:7:11:7:27 | 'Hi from client!' | server.js:7:38:7:44 | message |
|
||||
| client-custom.js:17:30:17:46 | 'Hi from client!' | server-custom.js:7:38:7:44 | message |
|
||||
| client-custom.js:17:30:17:46 | 'Hi from client!' | server-custom.js:17:38:17:44 | message |
|
||||
| client-custom.js:17:30:17:46 | 'Hi from client!' | server.js:7:38:7:44 | message |
|
||||
| client.js:7:11:7:27 | 'Hi from client!' | server-custom.js:7:38:7:44 | message |
|
||||
| client.js:7:11:7:27 | 'Hi from client!' | server-custom.js:17:38:17:44 | message |
|
||||
| client.js:7:11:7:27 | 'Hi from client!' | server.js:7:38:7:44 | message |
|
||||
| client.js:15:32:15:44 | require('ws') | client-custom.js:1:9:1:21 | MyWebSocketWS |
|
||||
| client.js:16:40:16:72 | new Web ... e.org') | client-custom.js:1:24:1:44 | myWebSo ... nstance |
|
||||
| server-custom.js:11:11:11:27 | 'Hi from server!' | browser-custom.js:11:39:11:48 | event.data |
|
||||
| server-custom.js:11:11:11:27 | 'Hi from server!' | browser-custom.js:15:40:15:49 | event.data |
|
||||
| server-custom.js:11:11:11:27 | 'Hi from server!' | browser-custom.js:43:45:43:54 | event.data |
|
||||
| server-custom.js:11:11:11:27 | 'Hi from server!' | browser-custom.js:47:46:47:55 | event.data |
|
||||
| server-custom.js:11:11:11:27 | 'Hi from server!' | browser-custom.js:69:38:69:43 | e.data |
|
||||
| server-custom.js:11:11:11:27 | 'Hi from server!' | browser.js:9:39:9:48 | event.data |
|
||||
| server-custom.js:11:11:11:27 | 'Hi from server!' | browser.js:13:40:13:49 | event.data |
|
||||
| server-custom.js:11:11:11:27 | 'Hi from server!' | client-custom.js:10:37:10:40 | data |
|
||||
| server-custom.js:11:11:11:27 | 'Hi from server!' | client-custom.js:20:56:20:59 | data |
|
||||
| server-custom.js:11:11:11:27 | 'Hi from server!' | client.js:10:37:10:40 | data |
|
||||
| server-custom.js:21:11:21:27 | 'Hi from server!' | browser-custom.js:11:39:11:48 | event.data |
|
||||
| server-custom.js:21:11:21:27 | 'Hi from server!' | browser-custom.js:15:40:15:49 | event.data |
|
||||
| server-custom.js:21:11:21:27 | 'Hi from server!' | browser-custom.js:43:45:43:54 | event.data |
|
||||
| server-custom.js:21:11:21:27 | 'Hi from server!' | browser-custom.js:47:46:47:55 | event.data |
|
||||
| server-custom.js:21:11:21:27 | 'Hi from server!' | browser-custom.js:69:38:69:43 | e.data |
|
||||
| server-custom.js:21:11:21:27 | 'Hi from server!' | browser.js:9:39:9:48 | event.data |
|
||||
| server-custom.js:21:11:21:27 | 'Hi from server!' | browser.js:13:40:13:49 | event.data |
|
||||
| server-custom.js:21:11:21:27 | 'Hi from server!' | client-custom.js:10:37:10:40 | data |
|
||||
| server-custom.js:21:11:21:27 | 'Hi from server!' | client-custom.js:20:56:20:59 | data |
|
||||
| server-custom.js:21:11:21:27 | 'Hi from server!' | client.js:10:37:10:40 | data |
|
||||
| server.js:11:11:11:27 | 'Hi from server!' | browser-custom.js:11:39:11:48 | event.data |
|
||||
| server.js:11:11:11:27 | 'Hi from server!' | browser-custom.js:15:40:15:49 | event.data |
|
||||
| server.js:11:11:11:27 | 'Hi from server!' | browser-custom.js:43:45:43:54 | event.data |
|
||||
| server.js:11:11:11:27 | 'Hi from server!' | browser-custom.js:47:46:47:55 | event.data |
|
||||
| server.js:11:11:11:27 | 'Hi from server!' | browser-custom.js:69:38:69:43 | e.data |
|
||||
| server.js:11:11:11:27 | 'Hi from server!' | browser.js:9:39:9:48 | event.data |
|
||||
| server.js:11:11:11:27 | 'Hi from server!' | browser.js:13:40:13:49 | event.data |
|
||||
| server.js:11:11:11:27 | 'Hi from server!' | client-custom.js:10:37:10:40 | data |
|
||||
| server.js:11:11:11:27 | 'Hi from server!' | client-custom.js:20:56:20:59 | data |
|
||||
| server.js:11:11:11:27 | 'Hi from server!' | client.js:10:37:10:40 | data |
|
||||
| server.js:15:36:15:55 | require('ws').Server | server-custom.js:1:9:1:25 | MyWebSocketServer |
|
||||
| server.js:16:44:16:79 | new Web ... 8080 }) | server-custom.js:1:28:1:52 | myWebSo ... nstance |
|
||||
| sockjs.js:11:20:11:50 | JSON.st ... .test)) | browser-custom.js:27:26:27:31 | e.data |
|
||||
| sockjs.js:11:20:11:50 | JSON.st ... .test)) | browser-custom.js:32:42:32:51 | event.data |
|
||||
| sockjs.js:11:20:11:50 | JSON.st ... .test)) | browser-custom.js:58:32:58:37 | e.data |
|
||||
| sockjs.js:11:20:11:50 | JSON.st ... .test)) | browser-custom.js:63:48:63:57 | event.data |
|
||||
| sockjs.js:11:20:11:50 | JSON.st ... .test)) | browser.js:25:26:25:31 | e.data |
|
||||
| sockjs.js:11:20:11:50 | JSON.st ... .test)) | browser.js:30:42:30:51 | event.data |
|
||||
remoteFlow
|
||||
| browser-custom.js:11:39:11:48 | event.data |
|
||||
| browser-custom.js:15:40:15:49 | event.data |
|
||||
| browser-custom.js:27:26:27:31 | e.data |
|
||||
| browser-custom.js:32:42:32:51 | event.data |
|
||||
| browser-custom.js:43:45:43:54 | event.data |
|
||||
| browser-custom.js:47:46:47:55 | event.data |
|
||||
| browser-custom.js:58:32:58:37 | e.data |
|
||||
| browser-custom.js:63:48:63:57 | event.data |
|
||||
| browser-custom.js:69:38:69:43 | e.data |
|
||||
| browser.js:9:39:9:48 | event.data |
|
||||
| browser.js:13:40:13:49 | event.data |
|
||||
| browser.js:25:26:25:31 | e.data |
|
||||
| browser.js:30:42:30:51 | event.data |
|
||||
| client-custom.js:10:37:10:40 | data |
|
||||
| client-custom.js:20:56:20:59 | data |
|
||||
| client.js:10:37:10:40 | data |
|
||||
| server-custom.js:7:38:7:44 | message |
|
||||
| server-custom.js:17:38:17:44 | message |
|
||||
| server.js:7:38:7:44 | message |
|
||||
| sockjs.js:9:31:9:37 | message |
|
||||
serverReceive
|
||||
| server-custom.js:7:3:9:4 | ws.on(' ... );\\n\\t\\t}) |
|
||||
| server-custom.js:17:3:19:4 | ws.on(' ... );\\n\\t\\t}) |
|
||||
| server.js:7:3:9:4 | ws.on(' ... );\\n\\t\\t}) |
|
||||
| sockjs.js:9:5:12:6 | conn.on ... \\n }) |
|
||||
serverSend
|
||||
| server-custom.js:11:3:11:28 | ws.send ... rver!') |
|
||||
| server-custom.js:21:3:21:28 | ws.send ... rver!') |
|
||||
| server.js:11:3:11:28 | ws.send ... rver!') |
|
||||
| sockjs.js:11:9:11:51 | conn.wr ... test))) |
|
||||
serverSocket
|
||||
| server-custom.js:6:43:6:44 | ws |
|
||||
| server-custom.js:16:65:16:66 | ws |
|
||||
| server.js:6:43:6:44 | ws |
|
||||
| sockjs.js:8:40:8:43 | conn |
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
query: test.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
@@ -52,6 +52,19 @@
|
||||
| handlebars.js:11:32:11:39 | filePath | handlebars.js:29:46:29:60 | req.params.path | handlebars.js:11:32:11:39 | filePath | This path depends on a $@. | handlebars.js:29:46:29:60 | req.params.path | user-provided value |
|
||||
| handlebars.js:15:25:15:32 | filePath | handlebars.js:43:15:43:29 | req.params.path | handlebars.js:15:25:15:32 | filePath | This path depends on a $@. | handlebars.js:43:15:43:29 | req.params.path | user-provided value |
|
||||
| hapi.js:15:44:15:51 | filepath | hapi.js:14:30:14:51 | request ... ilepath | hapi.js:15:44:15:51 | filepath | This path depends on a $@. | hapi.js:14:30:14:51 | request ... ilepath | user-provided value |
|
||||
| make-dir.js:9:25:9:28 | file | make-dir.js:7:18:7:31 | req.query.file | make-dir.js:9:25:9:28 | file | This path depends on a $@. | make-dir.js:7:18:7:31 | req.query.file | user-provided value |
|
||||
| make-dir.js:10:23:10:26 | file | make-dir.js:7:18:7:31 | req.query.file | make-dir.js:10:23:10:26 | file | This path depends on a $@. | make-dir.js:7:18:7:31 | req.query.file | user-provided value |
|
||||
| mkdirp.js:11:12:11:18 | dirPath | mkdirp.js:9:42:9:59 | req.query.filename | mkdirp.js:11:12:11:18 | dirPath | This path depends on a $@. | mkdirp.js:9:42:9:59 | req.query.filename | user-provided value |
|
||||
| mkdirp.js:12:17:12:23 | dirPath | mkdirp.js:9:42:9:59 | req.query.filename | mkdirp.js:12:17:12:23 | dirPath | This path depends on a $@. | mkdirp.js:9:42:9:59 | req.query.filename | user-provided value |
|
||||
| mkdirp.js:13:23:13:29 | dirPath | mkdirp.js:9:42:9:59 | req.query.filename | mkdirp.js:13:23:13:29 | dirPath | This path depends on a $@. | mkdirp.js:9:42:9:59 | req.query.filename | user-provided value |
|
||||
| mkdirp.js:14:19:14:25 | dirPath | mkdirp.js:9:42:9:59 | req.query.filename | mkdirp.js:14:19:14:25 | dirPath | This path depends on a $@. | mkdirp.js:9:42:9:59 | req.query.filename | user-provided value |
|
||||
| mkdirp.js:15:19:15:25 | dirPath | mkdirp.js:9:42:9:59 | req.query.filename | mkdirp.js:15:19:15:25 | dirPath | This path depends on a $@. | mkdirp.js:9:42:9:59 | req.query.filename | user-provided value |
|
||||
| mkdirp.js:16:23:16:29 | dirPath | mkdirp.js:9:42:9:59 | req.query.filename | mkdirp.js:16:23:16:29 | dirPath | This path depends on a $@. | mkdirp.js:9:42:9:59 | req.query.filename | user-provided value |
|
||||
| mkdirp.js:17:25:17:31 | dirPath | mkdirp.js:9:42:9:59 | req.query.filename | mkdirp.js:17:25:17:31 | dirPath | This path depends on a $@. | mkdirp.js:9:42:9:59 | req.query.filename | user-provided value |
|
||||
| mkdirp.js:18:25:18:31 | dirPath | mkdirp.js:9:42:9:59 | req.query.filename | mkdirp.js:18:25:18:31 | dirPath | This path depends on a $@. | mkdirp.js:9:42:9:59 | req.query.filename | user-provided value |
|
||||
| mkdirp.js:19:29:19:35 | dirPath | mkdirp.js:9:42:9:59 | req.query.filename | mkdirp.js:19:29:19:35 | dirPath | This path depends on a $@. | mkdirp.js:9:42:9:59 | req.query.filename | user-provided value |
|
||||
| mkdirp.js:20:29:20:35 | dirPath | mkdirp.js:9:42:9:59 | req.query.filename | mkdirp.js:20:29:20:35 | dirPath | This path depends on a $@. | mkdirp.js:9:42:9:59 | req.query.filename | user-provided value |
|
||||
| mkdirp.js:21:23:21:29 | dirPath | mkdirp.js:9:42:9:59 | req.query.filename | mkdirp.js:21:23:21:29 | dirPath | This path depends on a $@. | mkdirp.js:9:42:9:59 | req.query.filename | user-provided value |
|
||||
| more-fs-extra.js:10:15:10:22 | filename | more-fs-extra.js:8:26:8:33 | req.body | more-fs-extra.js:10:15:10:22 | filename | This path depends on a $@. | more-fs-extra.js:8:26:8:33 | req.body | user-provided value |
|
||||
| more-fs-extra.js:11:11:11:18 | filename | more-fs-extra.js:8:26:8:33 | req.body | more-fs-extra.js:11:11:11:18 | filename | This path depends on a $@. | more-fs-extra.js:8:26:8:33 | req.body | user-provided value |
|
||||
| more-fs-extra.js:12:14:12:21 | filename | more-fs-extra.js:8:26:8:33 | req.body | more-fs-extra.js:12:14:12:21 | filename | This path depends on a $@. | more-fs-extra.js:8:26:8:33 | req.body | user-provided value |
|
||||
@@ -140,6 +153,8 @@
|
||||
| normalizedPaths.js:408:19:408:60 | pathMod ... t('/')) | normalizedPaths.js:408:38:408:48 | req.query.x | normalizedPaths.js:408:19:408:60 | pathMod ... t('/')) | This path depends on a $@. | normalizedPaths.js:408:38:408:48 | req.query.x | user-provided value |
|
||||
| normalizedPaths.js:415:19:415:22 | path | normalizedPaths.js:412:35:412:45 | req.query.x | normalizedPaths.js:415:19:415:22 | path | This path depends on a $@. | normalizedPaths.js:412:35:412:45 | req.query.x | user-provided value |
|
||||
| normalizedPaths.js:426:21:426:24 | path | normalizedPaths.js:412:35:412:45 | req.query.x | normalizedPaths.js:426:21:426:24 | path | This path depends on a $@. | normalizedPaths.js:412:35:412:45 | req.query.x | user-provided value |
|
||||
| open.js:9:10:9:13 | file | open.js:7:18:7:31 | req.query.file | open.js:9:10:9:13 | file | This path depends on a $@. | open.js:7:18:7:31 | req.query.file | user-provided value |
|
||||
| open.js:10:13:10:16 | file | open.js:7:18:7:31 | req.query.file | open.js:10:13:10:16 | file | This path depends on a $@. | open.js:7:18:7:31 | req.query.file | user-provided value |
|
||||
| other-fs-libraries.js:11:19:11:22 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:11:19:11:22 | path | This path depends on a $@. | other-fs-libraries.js:9:24:9:30 | req.url | user-provided value |
|
||||
| other-fs-libraries.js:12:27:12:30 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:12:27:12:30 | path | This path depends on a $@. | other-fs-libraries.js:9:24:9:30 | req.url | user-provided value |
|
||||
| other-fs-libraries.js:13:24:13:27 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:13:24:13:27 | path | This path depends on a $@. | other-fs-libraries.js:9:24:9:30 | req.url | user-provided value |
|
||||
@@ -168,6 +183,26 @@
|
||||
| prettier.js:11:44:11:44 | p | prettier.js:6:13:6:13 | p | prettier.js:11:44:11:44 | p | This path depends on a $@. | prettier.js:6:13:6:13 | p | user-provided value |
|
||||
| pupeteer.js:9:28:9:34 | tainted | pupeteer.js:5:28:5:53 | parseTo ... t).name | pupeteer.js:9:28:9:34 | tainted | This path depends on a $@. | pupeteer.js:5:28:5:53 | parseTo ... t).name | user-provided value |
|
||||
| pupeteer.js:13:37:13:43 | tainted | pupeteer.js:5:28:5:53 | parseTo ... t).name | pupeteer.js:13:37:13:43 | tainted | This path depends on a $@. | pupeteer.js:5:28:5:53 | parseTo ... t).name | user-provided value |
|
||||
| rimraf.js:10:17:10:20 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:10:17:10:20 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:11:23:11:26 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:11:23:11:26 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:12:19:12:22 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:12:19:12:22 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:13:25:13:28 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:13:25:13:28 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:14:24:14:27 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:14:24:14:27 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:15:23:15:26 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:15:23:15:26 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:16:25:16:28 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:16:25:16:28 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:17:19:17:22 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:17:19:17:22 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:18:24:18:27 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:18:24:18:27 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:19:23:19:26 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:19:23:19:26 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:20:26:20:29 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:20:26:20:29 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:21:20:21:23 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:21:20:21:23 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:22:25:22:28 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:22:25:22:28 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:23:24:23:27 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:23:24:23:27 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:24:23:24:26 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:24:23:24:26 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:25:28:25:31 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:25:28:25:31 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:26:27:26:30 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:26:27:26:30 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:27:22:27:25 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:27:22:27:25 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:28:18:28:21 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:28:18:28:21 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| rimraf.js:29:23:29:26 | path | rimraf.js:8:22:8:29 | req.body | rimraf.js:29:23:29:26 | path | This path depends on a $@. | rimraf.js:8:22:8:29 | req.body | user-provided value |
|
||||
| sharedlib-repro.js:22:18:22:25 | filepath | sharedlib-repro.js:13:22:13:43 | req.par ... spaceId | sharedlib-repro.js:22:18:22:25 | filepath | This path depends on a $@. | sharedlib-repro.js:13:22:13:43 | req.par ... spaceId | user-provided value |
|
||||
| tainted-access-paths.js:8:19:8:22 | path | tainted-access-paths.js:6:24:6:30 | req.url | tainted-access-paths.js:8:19:8:22 | path | This path depends on a $@. | tainted-access-paths.js:6:24:6:30 | req.url | user-provided value |
|
||||
| tainted-access-paths.js:12:19:12:25 | obj.sub | tainted-access-paths.js:6:24:6:30 | req.url | tainted-access-paths.js:12:19:12:25 | obj.sub | This path depends on a $@. | tainted-access-paths.js:6:24:6:30 | req.url | user-provided value |
|
||||
@@ -370,6 +405,23 @@ edges
|
||||
| handlebars.js:43:15:43:29 | req.params.path | handlebars.js:13:73:13:80 | filePath | provenance | |
|
||||
| hapi.js:14:19:14:51 | filepath | hapi.js:15:44:15:51 | filepath | provenance | |
|
||||
| hapi.js:14:30:14:51 | request ... ilepath | hapi.js:14:19:14:51 | filepath | provenance | |
|
||||
| make-dir.js:7:11:7:31 | file | make-dir.js:9:25:9:28 | file | provenance | |
|
||||
| make-dir.js:7:11:7:31 | file | make-dir.js:10:23:10:26 | file | provenance | |
|
||||
| make-dir.js:7:18:7:31 | req.query.file | make-dir.js:7:11:7:31 | file | provenance | |
|
||||
| mkdirp.js:9:11:9:76 | dirPath | mkdirp.js:11:12:11:18 | dirPath | provenance | |
|
||||
| mkdirp.js:9:11:9:76 | dirPath | mkdirp.js:12:17:12:23 | dirPath | provenance | |
|
||||
| mkdirp.js:9:11:9:76 | dirPath | mkdirp.js:13:23:13:29 | dirPath | provenance | |
|
||||
| mkdirp.js:9:11:9:76 | dirPath | mkdirp.js:14:19:14:25 | dirPath | provenance | |
|
||||
| mkdirp.js:9:11:9:76 | dirPath | mkdirp.js:15:19:15:25 | dirPath | provenance | |
|
||||
| mkdirp.js:9:11:9:76 | dirPath | mkdirp.js:16:23:16:29 | dirPath | provenance | |
|
||||
| mkdirp.js:9:11:9:76 | dirPath | mkdirp.js:17:25:17:31 | dirPath | provenance | |
|
||||
| mkdirp.js:9:11:9:76 | dirPath | mkdirp.js:18:25:18:31 | dirPath | provenance | |
|
||||
| mkdirp.js:9:11:9:76 | dirPath | mkdirp.js:19:29:19:35 | dirPath | provenance | |
|
||||
| mkdirp.js:9:11:9:76 | dirPath | mkdirp.js:20:29:20:35 | dirPath | provenance | |
|
||||
| mkdirp.js:9:11:9:76 | dirPath | mkdirp.js:21:23:21:29 | dirPath | provenance | |
|
||||
| mkdirp.js:9:21:9:76 | path.jo ... ltDir') | mkdirp.js:9:11:9:76 | dirPath | provenance | |
|
||||
| mkdirp.js:9:42:9:59 | req.query.filename | mkdirp.js:9:42:9:75 | req.que ... ultDir' | provenance | |
|
||||
| mkdirp.js:9:42:9:75 | req.que ... ultDir' | mkdirp.js:9:21:9:76 | path.jo ... ltDir') | provenance | Config |
|
||||
| more-fs-extra.js:8:11:8:22 | { filename } | more-fs-extra.js:8:13:8:20 | filename | provenance | Config |
|
||||
| more-fs-extra.js:8:11:8:33 | filename | more-fs-extra.js:10:15:10:22 | filename | provenance | |
|
||||
| more-fs-extra.js:8:11:8:33 | filename | more-fs-extra.js:11:11:11:18 | filename | provenance | |
|
||||
@@ -541,6 +593,9 @@ edges
|
||||
| normalizedPaths.js:412:7:412:46 | path | normalizedPaths.js:426:21:426:24 | path | provenance | |
|
||||
| normalizedPaths.js:412:14:412:46 | pathMod ... uery.x) | normalizedPaths.js:412:7:412:46 | path | provenance | |
|
||||
| normalizedPaths.js:412:35:412:45 | req.query.x | normalizedPaths.js:412:14:412:46 | pathMod ... uery.x) | provenance | Config |
|
||||
| open.js:7:11:7:31 | file | open.js:9:10:9:13 | file | provenance | |
|
||||
| open.js:7:11:7:31 | file | open.js:10:13:10:16 | file | provenance | |
|
||||
| open.js:7:18:7:31 | req.query.file | open.js:7:11:7:31 | file | provenance | |
|
||||
| other-fs-libraries.js:9:7:9:48 | path | other-fs-libraries.js:11:19:11:22 | path | provenance | |
|
||||
| other-fs-libraries.js:9:7:9:48 | path | other-fs-libraries.js:12:27:12:30 | path | provenance | |
|
||||
| other-fs-libraries.js:9:7:9:48 | path | other-fs-libraries.js:13:24:13:27 | path | provenance | |
|
||||
@@ -594,6 +649,29 @@ edges
|
||||
| pupeteer.js:5:9:5:71 | tainted | pupeteer.js:13:37:13:43 | tainted | provenance | |
|
||||
| pupeteer.js:5:19:5:71 | "dir/" ... t.data" | pupeteer.js:5:9:5:71 | tainted | provenance | |
|
||||
| pupeteer.js:5:28:5:53 | parseTo ... t).name | pupeteer.js:5:19:5:71 | "dir/" ... t.data" | provenance | Config |
|
||||
| rimraf.js:8:11:8:18 | { path } | rimraf.js:8:13:8:16 | path | provenance | Config |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:10:17:10:20 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:11:23:11:26 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:12:19:12:22 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:13:25:13:28 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:14:24:14:27 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:15:23:15:26 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:16:25:16:28 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:17:19:17:22 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:18:24:18:27 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:19:23:19:26 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:20:26:20:29 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:21:20:21:23 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:22:25:22:28 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:23:24:23:27 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:24:23:24:26 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:25:28:25:31 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:26:27:26:30 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:27:22:27:25 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:28:18:28:21 | path | provenance | |
|
||||
| rimraf.js:8:11:8:29 | path | rimraf.js:29:23:29:26 | path | provenance | |
|
||||
| rimraf.js:8:13:8:16 | path | rimraf.js:8:11:8:29 | path | provenance | |
|
||||
| rimraf.js:8:22:8:29 | req.body | rimraf.js:8:11:8:18 | { path } | provenance | |
|
||||
| sharedlib-repro.js:13:22:13:43 | req.par ... spaceId | sharedlib-repro.js:21:27:21:34 | filepath | provenance | |
|
||||
| sharedlib-repro.js:21:27:21:34 | filepath | sharedlib-repro.js:22:18:22:25 | filepath | provenance | |
|
||||
| tainted-access-paths.js:6:7:6:48 | path | tainted-access-paths.js:8:19:8:22 | path | provenance | |
|
||||
@@ -876,6 +954,25 @@ nodes
|
||||
| hapi.js:14:19:14:51 | filepath | semmle.label | filepath |
|
||||
| hapi.js:14:30:14:51 | request ... ilepath | semmle.label | request ... ilepath |
|
||||
| hapi.js:15:44:15:51 | filepath | semmle.label | filepath |
|
||||
| make-dir.js:7:11:7:31 | file | semmle.label | file |
|
||||
| make-dir.js:7:18:7:31 | req.query.file | semmle.label | req.query.file |
|
||||
| make-dir.js:9:25:9:28 | file | semmle.label | file |
|
||||
| make-dir.js:10:23:10:26 | file | semmle.label | file |
|
||||
| mkdirp.js:9:11:9:76 | dirPath | semmle.label | dirPath |
|
||||
| mkdirp.js:9:21:9:76 | path.jo ... ltDir') | semmle.label | path.jo ... ltDir') |
|
||||
| mkdirp.js:9:42:9:59 | req.query.filename | semmle.label | req.query.filename |
|
||||
| mkdirp.js:9:42:9:75 | req.que ... ultDir' | semmle.label | req.que ... ultDir' |
|
||||
| mkdirp.js:11:12:11:18 | dirPath | semmle.label | dirPath |
|
||||
| mkdirp.js:12:17:12:23 | dirPath | semmle.label | dirPath |
|
||||
| mkdirp.js:13:23:13:29 | dirPath | semmle.label | dirPath |
|
||||
| mkdirp.js:14:19:14:25 | dirPath | semmle.label | dirPath |
|
||||
| mkdirp.js:15:19:15:25 | dirPath | semmle.label | dirPath |
|
||||
| mkdirp.js:16:23:16:29 | dirPath | semmle.label | dirPath |
|
||||
| mkdirp.js:17:25:17:31 | dirPath | semmle.label | dirPath |
|
||||
| mkdirp.js:18:25:18:31 | dirPath | semmle.label | dirPath |
|
||||
| mkdirp.js:19:29:19:35 | dirPath | semmle.label | dirPath |
|
||||
| mkdirp.js:20:29:20:35 | dirPath | semmle.label | dirPath |
|
||||
| mkdirp.js:21:23:21:29 | dirPath | semmle.label | dirPath |
|
||||
| more-fs-extra.js:8:11:8:22 | { filename } | semmle.label | { filename } |
|
||||
| more-fs-extra.js:8:11:8:33 | filename | semmle.label | filename |
|
||||
| more-fs-extra.js:8:13:8:20 | filename | semmle.label | filename |
|
||||
@@ -1073,6 +1170,10 @@ nodes
|
||||
| normalizedPaths.js:412:35:412:45 | req.query.x | semmle.label | req.query.x |
|
||||
| normalizedPaths.js:415:19:415:22 | path | semmle.label | path |
|
||||
| normalizedPaths.js:426:21:426:24 | path | semmle.label | path |
|
||||
| open.js:7:11:7:31 | file | semmle.label | file |
|
||||
| open.js:7:18:7:31 | req.query.file | semmle.label | req.query.file |
|
||||
| open.js:9:10:9:13 | file | semmle.label | file |
|
||||
| open.js:10:13:10:16 | file | semmle.label | file |
|
||||
| other-fs-libraries.js:9:7:9:48 | path | semmle.label | path |
|
||||
| other-fs-libraries.js:9:14:9:37 | url.par ... , true) | semmle.label | url.par ... , true) |
|
||||
| other-fs-libraries.js:9:14:9:43 | url.par ... ).query | semmle.label | url.par ... ).query |
|
||||
@@ -1133,6 +1234,30 @@ nodes
|
||||
| pupeteer.js:5:28:5:53 | parseTo ... t).name | semmle.label | parseTo ... t).name |
|
||||
| pupeteer.js:9:28:9:34 | tainted | semmle.label | tainted |
|
||||
| pupeteer.js:13:37:13:43 | tainted | semmle.label | tainted |
|
||||
| rimraf.js:8:11:8:18 | { path } | semmle.label | { path } |
|
||||
| rimraf.js:8:11:8:29 | path | semmle.label | path |
|
||||
| rimraf.js:8:13:8:16 | path | semmle.label | path |
|
||||
| rimraf.js:8:22:8:29 | req.body | semmle.label | req.body |
|
||||
| rimraf.js:10:17:10:20 | path | semmle.label | path |
|
||||
| rimraf.js:11:23:11:26 | path | semmle.label | path |
|
||||
| rimraf.js:12:19:12:22 | path | semmle.label | path |
|
||||
| rimraf.js:13:25:13:28 | path | semmle.label | path |
|
||||
| rimraf.js:14:24:14:27 | path | semmle.label | path |
|
||||
| rimraf.js:15:23:15:26 | path | semmle.label | path |
|
||||
| rimraf.js:16:25:16:28 | path | semmle.label | path |
|
||||
| rimraf.js:17:19:17:22 | path | semmle.label | path |
|
||||
| rimraf.js:18:24:18:27 | path | semmle.label | path |
|
||||
| rimraf.js:19:23:19:26 | path | semmle.label | path |
|
||||
| rimraf.js:20:26:20:29 | path | semmle.label | path |
|
||||
| rimraf.js:21:20:21:23 | path | semmle.label | path |
|
||||
| rimraf.js:22:25:22:28 | path | semmle.label | path |
|
||||
| rimraf.js:23:24:23:27 | path | semmle.label | path |
|
||||
| rimraf.js:24:23:24:26 | path | semmle.label | path |
|
||||
| rimraf.js:25:28:25:31 | path | semmle.label | path |
|
||||
| rimraf.js:26:27:26:30 | path | semmle.label | path |
|
||||
| rimraf.js:27:22:27:25 | path | semmle.label | path |
|
||||
| rimraf.js:28:18:28:21 | path | semmle.label | path |
|
||||
| rimraf.js:29:23:29:26 | path | semmle.label | path |
|
||||
| sharedlib-repro.js:13:22:13:43 | req.par ... spaceId | semmle.label | req.par ... spaceId |
|
||||
| sharedlib-repro.js:21:27:21:34 | filepath | semmle.label | filepath |
|
||||
| sharedlib-repro.js:22:18:22:25 | filepath | semmle.label | filepath |
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { makeDirectory, makeDirectorySync } from 'make-dir';
|
||||
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
|
||||
app.get('/makedir', async (req, res) => {
|
||||
const file = req.query.file; // $ Source
|
||||
|
||||
await makeDirectory(file); // $ Alert
|
||||
makeDirectorySync(file); // $ Alert
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
const express = require('express');
|
||||
const mkdirp = require('mkdirp');
|
||||
const path = require('path');
|
||||
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
|
||||
app.post('/foo', async (req, res) => {
|
||||
const dirPath = path.join(__dirname, req.query.filename || 'defaultDir'); // $ Source
|
||||
|
||||
mkdirp(dirPath); // $ Alert
|
||||
mkdirp.sync(dirPath); // $ Alert
|
||||
mkdirp.nativeSync(dirPath); // $ Alert
|
||||
mkdirp.native(dirPath); // $ Alert
|
||||
mkdirp.manual(dirPath); // $ Alert
|
||||
mkdirp.manualSync(dirPath); // $ Alert
|
||||
mkdirp.mkdirpNative(dirPath); // $ Alert
|
||||
mkdirp.mkdirpManual(dirPath); // $ Alert
|
||||
mkdirp.mkdirpManualSync(dirPath); // $ Alert
|
||||
mkdirp.mkdirpNativeSync(dirPath); // $ Alert
|
||||
mkdirp.mkdirpSync(dirPath); // $ Alert
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
import open, {openApp, apps} from 'open';
|
||||
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
|
||||
app.get('/open', (req, res) => {
|
||||
const file = req.query.file; // $ Source
|
||||
|
||||
open(file); // $ Alert
|
||||
openApp(file); // $ Alert
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
const express = require('express');
|
||||
const rimraf = require('rimraf');
|
||||
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
|
||||
app.post('/rmsync', async (req, res) => {
|
||||
const { path } = req.body; // $ Source
|
||||
|
||||
rimraf.sync(path); // $ Alert
|
||||
rimraf.rimrafSync(path); // $ Alert
|
||||
rimraf.native(path); // $ Alert
|
||||
await rimraf.native(path); // $ Alert
|
||||
rimraf.native.sync(path); // $ Alert
|
||||
rimraf.nativeSync(path); // $ Alert
|
||||
await rimraf.manual(path); // $ Alert
|
||||
rimraf.manual(path); // $ Alert
|
||||
rimraf.manual.sync(path); // $ Alert
|
||||
rimraf.manualSync(path); // $ Alert
|
||||
await rimraf.windows(path); // $ Alert
|
||||
rimraf.windows(path); // $ Alert
|
||||
rimraf.windows.sync(path); // $ Alert
|
||||
rimraf.windowsSync(path); // $ Alert
|
||||
rimraf.moveRemove(path); // $ Alert
|
||||
rimraf.moveRemove.sync(path); // $ Alert
|
||||
rimraf.moveRemoveSync(path); // $ Alert
|
||||
rimraf.posixSync(path); // $ Alert
|
||||
rimraf.posix(path); // $ Alert
|
||||
rimraf.posix.sync(path); // $ Alert
|
||||
});
|
||||
@@ -53,6 +53,7 @@
|
||||
| dates.js:57:31:57:101 | `Time i ... aint)}` | dates.js:54:36:54:55 | window.location.hash | dates.js:57:31:57:101 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:54:36:54:55 | window.location.hash | user-provided value |
|
||||
| dates.js:59:31:59:87 | `Time i ... aint)}` | dates.js:54:36:54:55 | window.location.hash | dates.js:59:31:59:87 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:54:36:54:55 | window.location.hash | user-provided value |
|
||||
| dates.js:61:31:61:88 | `Time i ... aint)}` | dates.js:54:36:54:55 | window.location.hash | dates.js:61:31:61:88 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:54:36:54:55 | window.location.hash | user-provided value |
|
||||
| dom.js:4:20:4:30 | window.name | dom.js:4:20:4:30 | window.name | dom.js:4:20:4:30 | window.name | Cross-site scripting vulnerability due to $@. | dom.js:4:20:4:30 | window.name | user-provided value |
|
||||
| dragAndDrop.ts:15:25:15:28 | html | dragAndDrop.ts:8:18:8:50 | dataTra ... /html') | dragAndDrop.ts:15:25:15:28 | html | Cross-site scripting vulnerability due to $@. | dragAndDrop.ts:8:18:8:50 | dataTra ... /html') | user-provided value |
|
||||
| dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') | dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') | dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') | Cross-site scripting vulnerability due to $@. | dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') | user-provided value |
|
||||
| dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') | dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') | dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') | Cross-site scripting vulnerability due to $@. | dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') | user-provided value |
|
||||
@@ -937,6 +938,7 @@ nodes
|
||||
| dates.js:61:31:61:88 | `Time i ... aint)}` | semmle.label | `Time i ... aint)}` |
|
||||
| dates.js:61:42:61:86 | dayjs.s ... (taint) | semmle.label | dayjs.s ... (taint) |
|
||||
| dates.js:61:81:61:85 | taint | semmle.label | taint |
|
||||
| dom.js:4:20:4:30 | window.name | semmle.label | window.name |
|
||||
| dragAndDrop.ts:8:11:8:50 | html | semmle.label | html |
|
||||
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') | semmle.label | dataTra ... /html') |
|
||||
| dragAndDrop.ts:15:25:15:28 | html | semmle.label | html |
|
||||
|
||||
@@ -138,6 +138,7 @@ nodes
|
||||
| dates.js:61:31:61:88 | `Time i ... aint)}` | semmle.label | `Time i ... aint)}` |
|
||||
| dates.js:61:42:61:86 | dayjs.s ... (taint) | semmle.label | dayjs.s ... (taint) |
|
||||
| dates.js:61:81:61:85 | taint | semmle.label | taint |
|
||||
| dom.js:4:20:4:30 | window.name | semmle.label | window.name |
|
||||
| dragAndDrop.ts:8:11:8:50 | html | semmle.label | html |
|
||||
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') | semmle.label | dataTra ... /html') |
|
||||
| dragAndDrop.ts:15:25:15:28 | html | semmle.label | html |
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
function t1() {
|
||||
const elm = document.getElementById("foo");
|
||||
const e2 = elm.getElementsByTagName("bar")[0];
|
||||
e2.innerHTML = window.name; // $ Alert
|
||||
}
|
||||
@@ -27,6 +27,14 @@
|
||||
| ReflectedXssContentTypes.js:39:13:39:35 | "FOO: " ... rams.id | ReflectedXssContentTypes.js:39:23:39:35 | req.params.id | ReflectedXssContentTypes.js:39:13:39:35 | "FOO: " ... rams.id | Cross-site scripting vulnerability due to a $@. | ReflectedXssContentTypes.js:39:23:39:35 | req.params.id | user-provided value |
|
||||
| ReflectedXssContentTypes.js:70:12:70:34 | "FOO: " ... rams.id | ReflectedXssContentTypes.js:70:22:70:34 | req.params.id | ReflectedXssContentTypes.js:70:12:70:34 | "FOO: " ... rams.id | Cross-site scripting vulnerability due to a $@. | ReflectedXssContentTypes.js:70:22:70:34 | req.params.id | user-provided value |
|
||||
| ReflectedXssGood3.js:139:12:139:27 | escapeHtml3(url) | ReflectedXssGood3.js:135:15:135:27 | req.params.id | ReflectedXssGood3.js:139:12:139:27 | escapeHtml3(url) | Cross-site scripting vulnerability due to a $@. | ReflectedXssGood3.js:135:15:135:27 | req.params.id | user-provided value |
|
||||
| app/api/route.ts:5:18:5:21 | body | app/api/route.ts:2:24:2:33 | req.json() | app/api/route.ts:5:18:5:21 | body | Cross-site scripting vulnerability due to a $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
|
||||
| app/api/route.ts:13:18:13:21 | body | app/api/route.ts:2:24:2:33 | req.json() | app/api/route.ts:13:18:13:21 | body | Cross-site scripting vulnerability due to a $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
|
||||
| app/api/route.ts:25:18:25:21 | body | app/api/route.ts:2:24:2:33 | req.json() | app/api/route.ts:25:18:25:21 | body | Cross-site scripting vulnerability due to a $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
|
||||
| app/api/route.ts:29:25:29:28 | body | app/api/route.ts:2:24:2:33 | req.json() | app/api/route.ts:29:25:29:28 | body | Cross-site scripting vulnerability due to a $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
|
||||
| app/api/routeNextRequest.ts:7:20:7:23 | body | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | app/api/routeNextRequest.ts:7:20:7:23 | body | Cross-site scripting vulnerability due to a $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
|
||||
| app/api/routeNextRequest.ts:15:20:15:23 | body | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | app/api/routeNextRequest.ts:15:20:15:23 | body | Cross-site scripting vulnerability due to a $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
|
||||
| app/api/routeNextRequest.ts:27:20:27:23 | body | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | app/api/routeNextRequest.ts:27:20:27:23 | body | Cross-site scripting vulnerability due to a $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
|
||||
| app/api/routeNextRequest.ts:31:27:31:30 | body | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | app/api/routeNextRequest.ts:31:27:31:30 | body | Cross-site scripting vulnerability due to a $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
|
||||
| etherpad.js:11:12:11:19 | response | etherpad.js:9:16:9:30 | req.query.jsonp | etherpad.js:11:12:11:19 | response | Cross-site scripting vulnerability due to a $@. | etherpad.js:9:16:9:30 | req.query.jsonp | user-provided value |
|
||||
| formatting.js:6:14:6:47 | util.fo ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to a $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
|
||||
| formatting.js:7:14:7:53 | require ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to a $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
|
||||
@@ -40,6 +48,15 @@
|
||||
| partial.js:28:14:28:18 | x + y | partial.js:31:47:31:53 | req.url | partial.js:28:14:28:18 | x + y | Cross-site scripting vulnerability due to a $@. | partial.js:31:47:31:53 | req.url | user-provided value |
|
||||
| partial.js:37:14:37:18 | x + y | partial.js:40:43:40:49 | req.url | partial.js:37:14:37:18 | x + y | Cross-site scripting vulnerability due to a $@. | partial.js:40:43:40:49 | req.url | user-provided value |
|
||||
| promises.js:6:25:6:25 | x | promises.js:5:44:5:57 | req.query.data | promises.js:6:25:6:25 | x | Cross-site scripting vulnerability due to a $@. | promises.js:5:44:5:57 | req.query.data | user-provided value |
|
||||
| response-object.js:9:18:9:21 | data | response-object.js:7:18:7:25 | req.body | response-object.js:9:18:9:21 | data | Cross-site scripting vulnerability due to a $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:10:18:10:21 | data | response-object.js:7:18:7:25 | req.body | response-object.js:10:18:10:21 | data | Cross-site scripting vulnerability due to a $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:11:18:11:21 | data | response-object.js:7:18:7:25 | req.body | response-object.js:11:18:11:21 | data | Cross-site scripting vulnerability due to a $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:14:18:14:21 | data | response-object.js:7:18:7:25 | req.body | response-object.js:14:18:14:21 | data | Cross-site scripting vulnerability due to a $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:17:18:17:21 | data | response-object.js:7:18:7:25 | req.body | response-object.js:17:18:17:21 | data | Cross-site scripting vulnerability due to a $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:23:18:23:21 | data | response-object.js:7:18:7:25 | req.body | response-object.js:23:18:23:21 | data | Cross-site scripting vulnerability due to a $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:26:18:26:21 | data | response-object.js:7:18:7:25 | req.body | response-object.js:26:18:26:21 | data | Cross-site scripting vulnerability due to a $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:34:18:34:21 | data | response-object.js:7:18:7:25 | req.body | response-object.js:34:18:34:21 | data | Cross-site scripting vulnerability due to a $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:38:18:38:21 | data | response-object.js:7:18:7:25 | req.body | response-object.js:38:18:38:21 | data | Cross-site scripting vulnerability due to a $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| tst2.js:7:12:7:12 | p | tst2.js:6:9:6:9 | p | tst2.js:7:12:7:12 | p | Cross-site scripting vulnerability due to a $@. | tst2.js:6:9:6:9 | p | user-provided value |
|
||||
| tst2.js:8:12:8:12 | r | tst2.js:6:12:6:15 | q: r | tst2.js:8:12:8:12 | r | Cross-site scripting vulnerability due to a $@. | tst2.js:6:12:6:15 | q: r | user-provided value |
|
||||
| tst2.js:18:12:18:12 | p | tst2.js:14:9:14:9 | p | tst2.js:18:12:18:12 | p | Cross-site scripting vulnerability due to a $@. | tst2.js:14:9:14:9 | p | user-provided value |
|
||||
@@ -119,6 +136,18 @@ edges
|
||||
| ReflectedXssGood3.js:135:15:135:27 | req.params.id | ReflectedXssGood3.js:135:9:135:27 | url | provenance | |
|
||||
| ReflectedXssGood3.js:139:24:139:26 | url | ReflectedXssGood3.js:68:22:68:26 | value | provenance | |
|
||||
| ReflectedXssGood3.js:139:24:139:26 | url | ReflectedXssGood3.js:139:12:139:27 | escapeHtml3(url) | provenance | |
|
||||
| app/api/route.ts:2:11:2:33 | body | app/api/route.ts:5:18:5:21 | body | provenance | |
|
||||
| app/api/route.ts:2:11:2:33 | body | app/api/route.ts:13:18:13:21 | body | provenance | |
|
||||
| app/api/route.ts:2:11:2:33 | body | app/api/route.ts:25:18:25:21 | body | provenance | |
|
||||
| app/api/route.ts:2:11:2:33 | body | app/api/route.ts:29:25:29:28 | body | provenance | |
|
||||
| app/api/route.ts:2:18:2:33 | await req.json() | app/api/route.ts:2:11:2:33 | body | provenance | |
|
||||
| app/api/route.ts:2:24:2:33 | req.json() | app/api/route.ts:2:18:2:33 | await req.json() | provenance | |
|
||||
| app/api/routeNextRequest.ts:4:9:4:31 | body | app/api/routeNextRequest.ts:7:20:7:23 | body | provenance | |
|
||||
| app/api/routeNextRequest.ts:4:9:4:31 | body | app/api/routeNextRequest.ts:15:20:15:23 | body | provenance | |
|
||||
| app/api/routeNextRequest.ts:4:9:4:31 | body | app/api/routeNextRequest.ts:27:20:27:23 | body | provenance | |
|
||||
| app/api/routeNextRequest.ts:4:9:4:31 | body | app/api/routeNextRequest.ts:31:27:31:30 | body | provenance | |
|
||||
| app/api/routeNextRequest.ts:4:16:4:31 | await req.json() | app/api/routeNextRequest.ts:4:9:4:31 | body | provenance | |
|
||||
| app/api/routeNextRequest.ts:4:22:4:31 | req.json() | app/api/routeNextRequest.ts:4:16:4:31 | await req.json() | provenance | |
|
||||
| etherpad.js:9:5:9:53 | response | etherpad.js:11:12:11:19 | response | provenance | |
|
||||
| etherpad.js:9:16:9:30 | req.query.jsonp | etherpad.js:9:5:9:53 | response | provenance | |
|
||||
| formatting.js:4:9:4:29 | evil | formatting.js:6:43:6:46 | evil | provenance | |
|
||||
@@ -149,6 +178,16 @@ edges
|
||||
| promises.js:5:36:5:42 | [post update] resolve [resolve-value] | promises.js:5:16:5:22 | resolve [Return] [resolve-value] | provenance | |
|
||||
| promises.js:5:44:5:57 | req.query.data | promises.js:5:36:5:42 | [post update] resolve [resolve-value] | provenance | |
|
||||
| promises.js:6:11:6:11 | x | promises.js:6:25:6:25 | x | provenance | |
|
||||
| response-object.js:7:11:7:25 | data | response-object.js:9:18:9:21 | data | provenance | |
|
||||
| response-object.js:7:11:7:25 | data | response-object.js:10:18:10:21 | data | provenance | |
|
||||
| response-object.js:7:11:7:25 | data | response-object.js:11:18:11:21 | data | provenance | |
|
||||
| response-object.js:7:11:7:25 | data | response-object.js:14:18:14:21 | data | provenance | |
|
||||
| response-object.js:7:11:7:25 | data | response-object.js:17:18:17:21 | data | provenance | |
|
||||
| response-object.js:7:11:7:25 | data | response-object.js:23:18:23:21 | data | provenance | |
|
||||
| response-object.js:7:11:7:25 | data | response-object.js:26:18:26:21 | data | provenance | |
|
||||
| response-object.js:7:11:7:25 | data | response-object.js:34:18:34:21 | data | provenance | |
|
||||
| response-object.js:7:11:7:25 | data | response-object.js:38:18:38:21 | data | provenance | |
|
||||
| response-object.js:7:18:7:25 | req.body | response-object.js:7:11:7:25 | data | provenance | |
|
||||
| tst2.js:6:7:6:30 | p | tst2.js:7:12:7:12 | p | provenance | |
|
||||
| tst2.js:6:7:6:30 | r | tst2.js:8:12:8:12 | r | provenance | |
|
||||
| tst2.js:6:9:6:9 | p | tst2.js:6:7:6:30 | p | provenance | |
|
||||
@@ -290,6 +329,20 @@ nodes
|
||||
| ReflectedXssGood3.js:135:15:135:27 | req.params.id | semmle.label | req.params.id |
|
||||
| ReflectedXssGood3.js:139:12:139:27 | escapeHtml3(url) | semmle.label | escapeHtml3(url) |
|
||||
| ReflectedXssGood3.js:139:24:139:26 | url | semmle.label | url |
|
||||
| app/api/route.ts:2:11:2:33 | body | semmle.label | body |
|
||||
| app/api/route.ts:2:18:2:33 | await req.json() | semmle.label | await req.json() |
|
||||
| app/api/route.ts:2:24:2:33 | req.json() | semmle.label | req.json() |
|
||||
| app/api/route.ts:5:18:5:21 | body | semmle.label | body |
|
||||
| app/api/route.ts:13:18:13:21 | body | semmle.label | body |
|
||||
| app/api/route.ts:25:18:25:21 | body | semmle.label | body |
|
||||
| app/api/route.ts:29:25:29:28 | body | semmle.label | body |
|
||||
| app/api/routeNextRequest.ts:4:9:4:31 | body | semmle.label | body |
|
||||
| app/api/routeNextRequest.ts:4:16:4:31 | await req.json() | semmle.label | await req.json() |
|
||||
| app/api/routeNextRequest.ts:4:22:4:31 | req.json() | semmle.label | req.json() |
|
||||
| app/api/routeNextRequest.ts:7:20:7:23 | body | semmle.label | body |
|
||||
| app/api/routeNextRequest.ts:15:20:15:23 | body | semmle.label | body |
|
||||
| app/api/routeNextRequest.ts:27:20:27:23 | body | semmle.label | body |
|
||||
| app/api/routeNextRequest.ts:31:27:31:30 | body | semmle.label | body |
|
||||
| etherpad.js:9:5:9:53 | response | semmle.label | response |
|
||||
| etherpad.js:9:16:9:30 | req.query.jsonp | semmle.label | req.query.jsonp |
|
||||
| etherpad.js:11:12:11:19 | response | semmle.label | response |
|
||||
@@ -332,6 +385,17 @@ nodes
|
||||
| promises.js:5:44:5:57 | req.query.data | semmle.label | req.query.data |
|
||||
| promises.js:6:11:6:11 | x | semmle.label | x |
|
||||
| promises.js:6:25:6:25 | x | semmle.label | x |
|
||||
| response-object.js:7:11:7:25 | data | semmle.label | data |
|
||||
| response-object.js:7:18:7:25 | req.body | semmle.label | req.body |
|
||||
| response-object.js:9:18:9:21 | data | semmle.label | data |
|
||||
| response-object.js:10:18:10:21 | data | semmle.label | data |
|
||||
| response-object.js:11:18:11:21 | data | semmle.label | data |
|
||||
| response-object.js:14:18:14:21 | data | semmle.label | data |
|
||||
| response-object.js:17:18:17:21 | data | semmle.label | data |
|
||||
| response-object.js:23:18:23:21 | data | semmle.label | data |
|
||||
| response-object.js:26:18:26:21 | data | semmle.label | data |
|
||||
| response-object.js:34:18:34:21 | data | semmle.label | data |
|
||||
| response-object.js:38:18:38:21 | data | semmle.label | data |
|
||||
| tst2.js:6:7:6:30 | p | semmle.label | p |
|
||||
| tst2.js:6:7:6:30 | r | semmle.label | r |
|
||||
| tst2.js:6:9:6:9 | p | semmle.label | p |
|
||||
|
||||
@@ -26,6 +26,14 @@
|
||||
| ReflectedXssContentTypes.js:39:13:39:35 | "FOO: " ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXssContentTypes.js:39:23:39:35 | req.params.id | user-provided value |
|
||||
| ReflectedXssContentTypes.js:70:12:70:34 | "FOO: " ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXssContentTypes.js:70:22:70:34 | req.params.id | user-provided value |
|
||||
| ReflectedXssGood3.js:139:12:139:27 | escapeHtml3(url) | Cross-site scripting vulnerability due to $@. | ReflectedXssGood3.js:135:15:135:27 | req.params.id | user-provided value |
|
||||
| app/api/route.ts:5:18:5:21 | body | Cross-site scripting vulnerability due to $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
|
||||
| app/api/route.ts:13:18:13:21 | body | Cross-site scripting vulnerability due to $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
|
||||
| app/api/route.ts:25:18:25:21 | body | Cross-site scripting vulnerability due to $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
|
||||
| app/api/route.ts:29:25:29:28 | body | Cross-site scripting vulnerability due to $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
|
||||
| app/api/routeNextRequest.ts:7:20:7:23 | body | Cross-site scripting vulnerability due to $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
|
||||
| app/api/routeNextRequest.ts:15:20:15:23 | body | Cross-site scripting vulnerability due to $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
|
||||
| app/api/routeNextRequest.ts:27:20:27:23 | body | Cross-site scripting vulnerability due to $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
|
||||
| app/api/routeNextRequest.ts:31:27:31:30 | body | Cross-site scripting vulnerability due to $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
|
||||
| formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
|
||||
| formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
|
||||
| live-server.js:6:13:6:50 | `<html> ... /html>` | Cross-site scripting vulnerability due to $@. | live-server.js:4:21:4:27 | req.url | user-provided value |
|
||||
@@ -38,6 +46,15 @@
|
||||
| partial.js:28:14:28:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:31:47:31:53 | req.url | user-provided value |
|
||||
| partial.js:37:14:37:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:40:43:40:49 | req.url | user-provided value |
|
||||
| promises.js:6:25:6:25 | x | Cross-site scripting vulnerability due to $@. | promises.js:5:44:5:57 | req.query.data | user-provided value |
|
||||
| response-object.js:9:18:9:21 | data | Cross-site scripting vulnerability due to $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:10:18:10:21 | data | Cross-site scripting vulnerability due to $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:11:18:11:21 | data | Cross-site scripting vulnerability due to $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:14:18:14:21 | data | Cross-site scripting vulnerability due to $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:17:18:17:21 | data | Cross-site scripting vulnerability due to $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:23:18:23:21 | data | Cross-site scripting vulnerability due to $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:26:18:26:21 | data | Cross-site scripting vulnerability due to $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:34:18:34:21 | data | Cross-site scripting vulnerability due to $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| response-object.js:38:18:38:21 | data | Cross-site scripting vulnerability due to $@. | response-object.js:7:18:7:25 | req.body | user-provided value |
|
||||
| tst2.js:7:12:7:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:6:9:6:9 | p | user-provided value |
|
||||
| tst2.js:8:12:8:12 | r | Cross-site scripting vulnerability due to $@. | tst2.js:6:12:6:15 | q: r | user-provided value |
|
||||
| tst2.js:18:12:18:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:14:9:14:9 | p | user-provided value |
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
export async function POST(req: Request) {
|
||||
const body = await req.json(); // $ Source
|
||||
|
||||
new Response(body, {headers: { 'Content-Type': 'application/json' }});
|
||||
new Response(body, {headers: { 'Content-Type': 'text/html' }}); // $ Alert
|
||||
|
||||
const headers2 = new Headers(req.headers);
|
||||
headers2.append('Content-Type', 'application/json');
|
||||
new Response(body, { headers: headers2 });
|
||||
|
||||
const headers3 = new Headers(req.headers);
|
||||
headers3.append('Content-Type', 'text/html');
|
||||
new Response(body, { headers: headers3 }); // $ Alert
|
||||
|
||||
const headers4 = new Headers({
|
||||
...Object.fromEntries(req.headers),
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
new Response(body, { headers: headers4 });
|
||||
|
||||
const headers5 = new Headers({
|
||||
...Object.fromEntries(req.headers),
|
||||
'Content-Type': 'text/html'
|
||||
});
|
||||
new Response(body, { headers: headers5 }); // $ Alert
|
||||
|
||||
const headers = new Headers(req.headers);
|
||||
headers.set('Content-Type', 'text/html');
|
||||
return new Response(body, { headers }); // $ Alert
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const body = await req.json(); // $ Source
|
||||
|
||||
new NextResponse(body, {headers: { 'Content-Type': 'application/json' }});
|
||||
new NextResponse(body, {headers: { 'Content-Type': 'text/html' }}); // $ Alert
|
||||
|
||||
const headers2 = new Headers(req.headers);
|
||||
headers2.append('Content-Type', 'application/json');
|
||||
new NextResponse(body, { headers: headers2 });
|
||||
|
||||
const headers3 = new Headers(req.headers);
|
||||
headers3.append('Content-Type', 'text/html');
|
||||
new NextResponse(body, { headers: headers3 }); // $ Alert
|
||||
|
||||
const headers4 = new Headers({
|
||||
...Object.fromEntries(req.headers),
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
new NextResponse(body, { headers: headers4 });
|
||||
|
||||
const headers5 = new Headers({
|
||||
...Object.fromEntries(req.headers),
|
||||
'Content-Type': 'text/html'
|
||||
});
|
||||
new NextResponse(body, { headers: headers5 }); // $ Alert
|
||||
|
||||
const headers = new Headers(req.headers);
|
||||
headers.set('Content-Type', 'text/html');
|
||||
return new NextResponse(body, { headers }); // $ Alert
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
const express = require('express');
|
||||
|
||||
// Note: We're using using express for the taint source in order to to test 'Response'
|
||||
// in isolation from the more complicated http frameworks.
|
||||
|
||||
express().get('/foo', (req) => {
|
||||
const data = req.body; // $ Source
|
||||
|
||||
new Response(data); // $ Alert
|
||||
new Response(data, {}); // $ Alert
|
||||
new Response(data, { headers: null }); // $ Alert
|
||||
|
||||
new Response(data, { headers: { 'content-type': 'text/plain'}});
|
||||
new Response(data, { headers: { 'content-type': 'text/html'}}); // $ Alert
|
||||
|
||||
new Response(data, { headers: { 'Content-Type': 'text/plain'}});
|
||||
new Response(data, { headers: { 'Content-Type': 'text/html'}}); // $ Alert
|
||||
|
||||
const headers1 = new Headers({ 'content-type': 'text/plain'});
|
||||
new Response(data, { headers: headers1 });
|
||||
|
||||
const headers2 = new Headers({ 'content-type': 'text/html'});
|
||||
new Response(data, { headers: headers2 }); // $ Alert
|
||||
|
||||
const headers3 = new Headers();
|
||||
new Response(data, { headers: headers3 }); // $ Alert
|
||||
|
||||
const headers4 = new Headers();
|
||||
headers4.set('content-type', 'text/plain');
|
||||
new Response(data, { headers: headers4 });
|
||||
|
||||
const headers5 = new Headers();
|
||||
headers5.set('content-type', 'text/html');
|
||||
new Response(data, { headers: headers5 }); // $ Alert
|
||||
|
||||
const headers6 = new Headers();
|
||||
headers6.set('unrelated-header', 'text/plain');
|
||||
new Response(data, { headers: headers6 }); // $ Alert
|
||||
});
|
||||
@@ -81,9 +81,12 @@ edges
|
||||
| pako.js:18:48:18:66 | zipFile.data.buffer | pako.js:18:33:18:67 | new Uin ... buffer) | provenance | Config |
|
||||
| pako.js:28:19:28:25 | zipFile | pako.js:29:36:29:42 | zipFile | provenance | |
|
||||
| pako.js:29:11:29:62 | myArray | pako.js:32:31:32:37 | myArray | provenance | |
|
||||
| pako.js:29:11:29:62 | myArray [ArrayElement] | pako.js:32:31:32:37 | myArray | provenance | |
|
||||
| pako.js:29:21:29:55 | new Uin ... buffer) | pako.js:29:11:29:62 | myArray | provenance | |
|
||||
| pako.js:29:21:29:55 | new Uin ... buffer) [ArrayElement] | pako.js:29:11:29:62 | myArray [ArrayElement] | provenance | |
|
||||
| pako.js:29:36:29:42 | zipFile | pako.js:29:36:29:54 | zipFile.data.buffer | provenance | |
|
||||
| pako.js:29:36:29:54 | zipFile.data.buffer | pako.js:29:21:29:55 | new Uin ... buffer) | provenance | Config |
|
||||
| pako.js:29:36:29:54 | zipFile.data.buffer | pako.js:29:21:29:55 | new Uin ... buffer) [ArrayElement] | provenance | |
|
||||
| unbzip2.js:12:5:12:43 | fs.crea ... lePath) | unbzip2.js:12:50:12:54 | bz2() | provenance | Config |
|
||||
| unbzip2.js:12:25:12:42 | req.query.FilePath | unbzip2.js:12:5:12:43 | fs.crea ... lePath) | provenance | Config |
|
||||
| unzipper.js:13:26:13:62 | Readabl ... e.data) | unzipper.js:16:23:16:63 | unzippe ... ath' }) | provenance | Config |
|
||||
@@ -183,7 +186,9 @@ nodes
|
||||
| pako.js:21:31:21:37 | myArray | semmle.label | myArray |
|
||||
| pako.js:28:19:28:25 | zipFile | semmle.label | zipFile |
|
||||
| pako.js:29:11:29:62 | myArray | semmle.label | myArray |
|
||||
| pako.js:29:11:29:62 | myArray [ArrayElement] | semmle.label | myArray [ArrayElement] |
|
||||
| pako.js:29:21:29:55 | new Uin ... buffer) | semmle.label | new Uin ... buffer) |
|
||||
| pako.js:29:21:29:55 | new Uin ... buffer) [ArrayElement] | semmle.label | new Uin ... buffer) [ArrayElement] |
|
||||
| pako.js:29:36:29:42 | zipFile | semmle.label | zipFile |
|
||||
| pako.js:29:36:29:54 | zipFile.data.buffer | semmle.label | zipFile.data.buffer |
|
||||
| pako.js:32:31:32:37 | myArray | semmle.label | myArray |
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
consistencyIssue
|
||||
resultInWrongFile
|
||||
@@ -1,25 +0,0 @@
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.RequestForgeryQuery as RequestForgery
|
||||
import semmle.javascript.security.dataflow.ClientSideRequestForgeryQuery as ClientSideRequestForgery
|
||||
deprecated import utils.test.ConsistencyChecking
|
||||
|
||||
query predicate resultInWrongFile(DataFlow::Node node) {
|
||||
exists(string filePattern |
|
||||
RequestForgery::RequestForgeryFlow::flowTo(node) and
|
||||
filePattern = ".*serverSide.*"
|
||||
or
|
||||
ClientSideRequestForgery::ClientSideRequestForgeryFlow::flowTo(node) and
|
||||
filePattern = ".*clientSide.*"
|
||||
|
|
||||
not node.getFile().getRelativePath().regexpMatch(filePattern)
|
||||
)
|
||||
}
|
||||
|
||||
deprecated class Consistency extends ConsistencyConfiguration {
|
||||
Consistency() { this = "Consistency" }
|
||||
|
||||
override DataFlow::Node getAnAlert() {
|
||||
RequestForgery::RequestForgeryFlow::flowTo(result) or
|
||||
ClientSideRequestForgery::ClientSideRequestForgeryFlow::flowTo(result)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export async function POST(req: Request) {
|
||||
const { url } = await req.json(); // $ Source[js/request-forgery]
|
||||
const res = await fetch(url); // $ Alert[js/request-forgery] Sink[js/request-forgery]
|
||||
return new Response(res.body, { headers: res.headers });
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const { url } = await req.json(); // $ Source[js/request-forgery]
|
||||
const res = await fetch(url); // $ Alert[js/request-forgery] Sink[js/request-forgery]
|
||||
const data = await res.text();
|
||||
return new NextResponse(data, { headers: res.headers });
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
export async function middleware(req: NextRequest) {
|
||||
const target = req.nextUrl // $ Source[js/request-forgery]
|
||||
const target2 = target.searchParams.get('target'); // $ Source[js/request-forgery]
|
||||
if (target) {
|
||||
const res = await fetch(target) // $ Alert[js/request-forgery] Sink[js/request-forgery]
|
||||
const data = await res.text()
|
||||
return new NextResponse(data)
|
||||
}
|
||||
if (target2) {
|
||||
const res = await fetch(target2); // $ Alert[js/request-forgery] Sink[js/request-forgery]
|
||||
const data = await res.text();
|
||||
return new NextResponse(data);
|
||||
}
|
||||
return NextResponse.next()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "next-edge-proxy-app",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "15.1.7"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,10 @@
|
||||
#select
|
||||
| Request/app/api/proxy/route2.serverSide.ts:5:21:5:30 | fetch(url) | Request/app/api/proxy/route2.serverSide.ts:4:25:4:34 | req.json() | Request/app/api/proxy/route2.serverSide.ts:5:27:5:29 | url | The $@ of this request depends on a $@. | Request/app/api/proxy/route2.serverSide.ts:5:27:5:29 | url | URL | Request/app/api/proxy/route2.serverSide.ts:4:25:4:34 | req.json() | user-provided value |
|
||||
| Request/app/api/proxy/route.serverSide.ts:3:21:3:30 | fetch(url) | Request/app/api/proxy/route.serverSide.ts:2:25:2:34 | req.json() | Request/app/api/proxy/route.serverSide.ts:3:27:3:29 | url | The $@ of this request depends on a $@. | Request/app/api/proxy/route.serverSide.ts:3:27:3:29 | url | URL | Request/app/api/proxy/route.serverSide.ts:2:25:2:34 | req.json() | user-provided value |
|
||||
| Request/middleware.ts:7:25:7:37 | fetch(target) | Request/middleware.ts:4:20:4:30 | req.nextUrl | Request/middleware.ts:7:31:7:36 | target | The $@ of this request depends on a $@. | Request/middleware.ts:7:31:7:36 | target | URL | Request/middleware.ts:4:20:4:30 | req.nextUrl | user-provided value |
|
||||
| Request/middleware.ts:12:27:12:40 | fetch(target2) | Request/middleware.ts:5:21:5:53 | target. ... arget') | Request/middleware.ts:12:33:12:39 | target2 | The $@ of this request depends on a $@. | Request/middleware.ts:12:33:12:39 | target2 | URL | Request/middleware.ts:5:21:5:53 | target. ... arget') | user-provided value |
|
||||
| apollo.serverSide.ts:8:39:8:64 | get(fil ... => {}) | apollo.serverSide.ts:7:36:7:44 | { files } | apollo.serverSide.ts:8:43:8:50 | file.url | The $@ of this request depends on a $@. | apollo.serverSide.ts:8:43:8:50 | file.url | URL | apollo.serverSide.ts:7:36:7:44 | { files } | user-provided value |
|
||||
| apollo.serverSide.ts:18:37:18:62 | get(fil ... => {}) | apollo.serverSide.ts:17:34:17:42 | { files } | apollo.serverSide.ts:18:41:18:48 | file.url | The $@ of this request depends on a $@. | apollo.serverSide.ts:18:41:18:48 | file.url | URL | apollo.serverSide.ts:17:34:17:42 | { files } | user-provided value |
|
||||
| axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | axiosInterceptors.serverSide.js:19:21:19:28 | req.body | axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | The $@ of this request depends on a $@. | axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | endpoint | axiosInterceptors.serverSide.js:19:21:19:28 | req.body | user-provided value |
|
||||
| serverSide.js:18:5:18:20 | request(tainted) | serverSide.js:14:29:14:35 | req.url | serverSide.js:18:13:18:19 | tainted | The $@ of this request depends on a $@. | serverSide.js:18:13:18:19 | tainted | URL | serverSide.js:14:29:14:35 | req.url | user-provided value |
|
||||
| serverSide.js:20:5:20:24 | request.get(tainted) | serverSide.js:14:29:14:35 | req.url | serverSide.js:20:17:20:23 | tainted | The $@ of this request depends on a $@. | serverSide.js:20:17:20:23 | tainted | URL | serverSide.js:14:29:14:35 | req.url | user-provided value |
|
||||
@@ -26,11 +31,28 @@
|
||||
| serverSide.js:125:5:128:6 | axios({ ... \\n }) | serverSide.js:123:29:123:35 | req.url | serverSide.js:127:14:127:20 | tainted | The $@ of this request depends on a $@. | serverSide.js:127:14:127:20 | tainted | URL | serverSide.js:123:29:123:35 | req.url | user-provided value |
|
||||
| serverSide.js:131:5:131:20 | axios.get(myUrl) | serverSide.js:123:29:123:35 | req.url | serverSide.js:131:15:131:19 | myUrl | The $@ of this request depends on a $@. | serverSide.js:131:15:131:19 | myUrl | URL | serverSide.js:123:29:123:35 | req.url | user-provided value |
|
||||
edges
|
||||
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:15 | { url } | Request/app/api/proxy/route2.serverSide.ts:4:9:4:34 | url | provenance | |
|
||||
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:34 | url | Request/app/api/proxy/route2.serverSide.ts:5:27:5:29 | url | provenance | |
|
||||
| Request/app/api/proxy/route2.serverSide.ts:4:19:4:34 | await req.json() | Request/app/api/proxy/route2.serverSide.ts:4:9:4:15 | { url } | provenance | |
|
||||
| Request/app/api/proxy/route2.serverSide.ts:4:25:4:34 | req.json() | Request/app/api/proxy/route2.serverSide.ts:4:19:4:34 | await req.json() | provenance | |
|
||||
| Request/app/api/proxy/route.serverSide.ts:2:9:2:15 | { url } | Request/app/api/proxy/route.serverSide.ts:2:9:2:34 | url | provenance | |
|
||||
| Request/app/api/proxy/route.serverSide.ts:2:9:2:34 | url | Request/app/api/proxy/route.serverSide.ts:3:27:3:29 | url | provenance | |
|
||||
| Request/app/api/proxy/route.serverSide.ts:2:19:2:34 | await req.json() | Request/app/api/proxy/route.serverSide.ts:2:9:2:15 | { url } | provenance | |
|
||||
| Request/app/api/proxy/route.serverSide.ts:2:25:2:34 | req.json() | Request/app/api/proxy/route.serverSide.ts:2:19:2:34 | await req.json() | provenance | |
|
||||
| Request/middleware.ts:4:11:4:30 | target | Request/middleware.ts:7:31:7:36 | target | provenance | |
|
||||
| Request/middleware.ts:4:20:4:30 | req.nextUrl | Request/middleware.ts:4:11:4:30 | target | provenance | |
|
||||
| Request/middleware.ts:5:11:5:53 | target2 | Request/middleware.ts:12:33:12:39 | target2 | provenance | |
|
||||
| Request/middleware.ts:5:21:5:53 | target. ... arget') | Request/middleware.ts:5:11:5:53 | target2 | provenance | |
|
||||
| apollo.serverSide.ts:7:36:7:44 | files | apollo.serverSide.ts:8:13:8:17 | files | provenance | |
|
||||
| apollo.serverSide.ts:7:36:7:44 | { files } | apollo.serverSide.ts:7:36:7:44 | files | provenance | |
|
||||
| apollo.serverSide.ts:8:13:8:17 | files | apollo.serverSide.ts:8:28:8:31 | file | provenance | |
|
||||
| apollo.serverSide.ts:8:28:8:31 | file | apollo.serverSide.ts:8:43:8:46 | file | provenance | |
|
||||
| apollo.serverSide.ts:8:43:8:46 | file | apollo.serverSide.ts:8:43:8:50 | file.url | provenance | |
|
||||
| apollo.serverSide.ts:17:34:17:42 | files | apollo.serverSide.ts:18:11:18:15 | files | provenance | |
|
||||
| apollo.serverSide.ts:17:34:17:42 | { files } | apollo.serverSide.ts:17:34:17:42 | files | provenance | |
|
||||
| apollo.serverSide.ts:18:11:18:15 | files | apollo.serverSide.ts:18:26:18:29 | file | provenance | |
|
||||
| apollo.serverSide.ts:18:26:18:29 | file | apollo.serverSide.ts:18:41:18:44 | file | provenance | |
|
||||
| apollo.serverSide.ts:18:41:18:44 | file | apollo.serverSide.ts:18:41:18:48 | file.url | provenance | |
|
||||
| axiosInterceptors.serverSide.js:19:11:19:17 | { url } | axiosInterceptors.serverSide.js:19:11:19:28 | url | provenance | |
|
||||
| axiosInterceptors.serverSide.js:19:11:19:28 | url | axiosInterceptors.serverSide.js:20:23:20:25 | url | provenance | |
|
||||
| axiosInterceptors.serverSide.js:19:21:19:28 | req.body | axiosInterceptors.serverSide.js:19:11:19:17 | { url } | provenance | |
|
||||
@@ -85,12 +107,34 @@ edges
|
||||
| serverSide.js:130:9:130:45 | myUrl | serverSide.js:131:15:131:19 | myUrl | provenance | |
|
||||
| serverSide.js:130:37:130:43 | tainted | serverSide.js:130:9:130:45 | myUrl | provenance | |
|
||||
nodes
|
||||
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:15 | { url } | semmle.label | { url } |
|
||||
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:34 | url | semmle.label | url |
|
||||
| Request/app/api/proxy/route2.serverSide.ts:4:19:4:34 | await req.json() | semmle.label | await req.json() |
|
||||
| Request/app/api/proxy/route2.serverSide.ts:4:25:4:34 | req.json() | semmle.label | req.json() |
|
||||
| Request/app/api/proxy/route2.serverSide.ts:5:27:5:29 | url | semmle.label | url |
|
||||
| Request/app/api/proxy/route.serverSide.ts:2:9:2:15 | { url } | semmle.label | { url } |
|
||||
| Request/app/api/proxy/route.serverSide.ts:2:9:2:34 | url | semmle.label | url |
|
||||
| Request/app/api/proxy/route.serverSide.ts:2:19:2:34 | await req.json() | semmle.label | await req.json() |
|
||||
| Request/app/api/proxy/route.serverSide.ts:2:25:2:34 | req.json() | semmle.label | req.json() |
|
||||
| Request/app/api/proxy/route.serverSide.ts:3:27:3:29 | url | semmle.label | url |
|
||||
| Request/middleware.ts:4:11:4:30 | target | semmle.label | target |
|
||||
| Request/middleware.ts:4:20:4:30 | req.nextUrl | semmle.label | req.nextUrl |
|
||||
| Request/middleware.ts:5:11:5:53 | target2 | semmle.label | target2 |
|
||||
| Request/middleware.ts:5:21:5:53 | target. ... arget') | semmle.label | target. ... arget') |
|
||||
| Request/middleware.ts:7:31:7:36 | target | semmle.label | target |
|
||||
| Request/middleware.ts:12:33:12:39 | target2 | semmle.label | target2 |
|
||||
| apollo.serverSide.ts:7:36:7:44 | files | semmle.label | files |
|
||||
| apollo.serverSide.ts:7:36:7:44 | { files } | semmle.label | { files } |
|
||||
| apollo.serverSide.ts:8:13:8:17 | files | semmle.label | files |
|
||||
| apollo.serverSide.ts:8:28:8:31 | file | semmle.label | file |
|
||||
| apollo.serverSide.ts:8:43:8:46 | file | semmle.label | file |
|
||||
| apollo.serverSide.ts:8:43:8:50 | file.url | semmle.label | file.url |
|
||||
| apollo.serverSide.ts:17:34:17:42 | files | semmle.label | files |
|
||||
| apollo.serverSide.ts:17:34:17:42 | { files } | semmle.label | { files } |
|
||||
| apollo.serverSide.ts:18:11:18:15 | files | semmle.label | files |
|
||||
| apollo.serverSide.ts:18:26:18:29 | file | semmle.label | file |
|
||||
| apollo.serverSide.ts:18:41:18:44 | file | semmle.label | file |
|
||||
| apollo.serverSide.ts:18:41:18:48 | file.url | semmle.label | file.url |
|
||||
| axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | semmle.label | userProvidedUrl |
|
||||
| axiosInterceptors.serverSide.js:19:11:19:17 | { url } | semmle.label | { url } |
|
||||
| axiosInterceptors.serverSide.js:19:11:19:28 | url | semmle.label | url |
|
||||
|
||||
@@ -14,8 +14,8 @@ function createApolloServer(typeDefs) {
|
||||
|
||||
const resolvers2 = {
|
||||
Mutation: {
|
||||
downloadFiles: async (_, { files }) => { // $ MISSING: Source[js/request-forgery]
|
||||
files.forEach((file) => { get(file.url, (res) => {}); }); // $ MISSING: Alert[js/request-forgery] Sink[js/request-forgery]
|
||||
downloadFiles: async (_, { files }) => { // $ Source[js/request-forgery]
|
||||
files.forEach((file) => { get(file.url, (res) => {}); }); // $ Alert[js/request-forgery] Sink[js/request-forgery]
|
||||
return true;
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user