mirror of
https://github.com/github/codeql.git
synced 2026-04-29 02:35:15 +02:00
add query for detecting insecure temprary files
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Provides default sources, sinks and sanitizers for reasoning about
|
||||
* insecure temporary file creation, as well as
|
||||
* extension points for adding your own.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/**
|
||||
* Classes and predicates for reasoning about insecure temporary file creation.
|
||||
*/
|
||||
module InsecureTemporaryFile {
|
||||
/**
|
||||
* A data flow source for insecure temporary file creation.
|
||||
*/
|
||||
abstract class Source extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A data flow sink for insecure temporary file creation.
|
||||
*/
|
||||
abstract class Sink extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A sanitizer for random insecure temporary file creation.
|
||||
*/
|
||||
abstract class Sanitizer extends DataFlow::Node { }
|
||||
|
||||
/** A call that opens a file with a given path. */
|
||||
class OpenFileCall extends DataFlow::CallNode {
|
||||
string methodName;
|
||||
|
||||
OpenFileCall() {
|
||||
methodName = ["open", "openSync", "writeFile", "writeFileSync"] and
|
||||
this = NodeJSLib::FS::moduleMember(methodName).getACall()
|
||||
}
|
||||
|
||||
DataFlow::Node getPath() { result = this.getArgument(0) }
|
||||
|
||||
DataFlow::Node getMode() {
|
||||
methodName = ["open", "openSync"] and
|
||||
result = this.getArgument(2)
|
||||
or
|
||||
methodName = ["writeFile", "writeFileSync"] and
|
||||
result = this.getOptionArgument(2, "mode")
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if the `mode` ensure no access to other users. */
|
||||
bindingset[mode]
|
||||
private predicate isSecureMode(int mode) {
|
||||
// the lowest 6 bits should be 0.
|
||||
// E.g. `0o600` is secure (each digit in a octal number is 3 bits)
|
||||
mode.bitAnd(1) = 0 and
|
||||
mode.bitAnd(2) = 0 and
|
||||
mode.bitAnd(4) = 0 and
|
||||
mode.bitAnd(8) = 0 and
|
||||
mode.bitAnd(16) = 0 and
|
||||
mode.bitAnd(32) = 0
|
||||
}
|
||||
|
||||
/** The path in a call that opens a file without specifying a secure `mode`. Seen as a sink for insecure temporary file creation. */
|
||||
class InsecureFileOpen extends Sink {
|
||||
InsecureFileOpen() {
|
||||
exists(OpenFileCall call |
|
||||
not exists(call.getMode())
|
||||
or
|
||||
exists(int mode | mode = call.getMode().getIntValue() | not isSecureMode(mode))
|
||||
|
|
||||
this = call.getPath()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A a string that references the global tmp dir. Seen as a source for insecure temporary file creation. */
|
||||
class OSTempDir extends Source {
|
||||
OSTempDir() {
|
||||
this = DataFlow::moduleImport("os").getAMemberCall("tmpdir")
|
||||
or
|
||||
this.getStringValue().matches("/tmp/%")
|
||||
}
|
||||
}
|
||||
|
||||
/** A non-first leaf in a string-concatenation. Seen as a sanitizer for insecure temporary file creation. */
|
||||
class NonFirstStringConcatLeaf extends Sanitizer {
|
||||
NonFirstStringConcatLeaf() {
|
||||
exists(StringOps::ConcatenationRoot root |
|
||||
this = root.getALeaf() and
|
||||
not this = root.getFirstLeaf()
|
||||
)
|
||||
or
|
||||
exists(DataFlow::CallNode join | join = DataFlow::moduleMember("path", "join").getACall() |
|
||||
this = join.getArgument([1 .. join.getNumArgument() - 1])
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Provides a taint tracking configuration for reasoning about insecure temporary
|
||||
* file creation.
|
||||
*
|
||||
* Note, for performance reasons: only import this file if
|
||||
* `InsecureTemporaryFile::Configuration` is needed, otherwise
|
||||
* `InsecureTemporaryFileCustomizations` should be imported instead.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import InsecureTemporaryFileCustomizations::InsecureTemporaryFile
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for reasoning about insecure temporary file creation.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "InsecureTemporaryFile" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
super.isSanitizer(node) or
|
||||
node instanceof Sanitizer
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user