JS: add models of logging frameworks

This commit is contained in:
Esben Sparre Andreasen
2018-08-08 11:28:50 +02:00
parent 87f9ecb442
commit 804c06bd59
5 changed files with 175 additions and 0 deletions

View File

@@ -58,6 +58,7 @@ import semmle.javascript.frameworks.DigitalOcean
import semmle.javascript.frameworks.Electron
import semmle.javascript.frameworks.jQuery
import semmle.javascript.frameworks.LodashUnderscore
import semmle.javascript.frameworks.Logging
import semmle.javascript.frameworks.HttpFrameworks
import semmle.javascript.frameworks.NoSQL
import semmle.javascript.frameworks.PkgCloud

View File

@@ -0,0 +1,137 @@
/**
* Provides classes for working with logging libraries.
*/
import javascript
/**
* A call to a logging mechanism.
*/
abstract class LoggerCall extends DataFlow::CallNode {
/**
* Gets a node that contributes to the logged message.
*/
abstract DataFlow::Node getAMessageComponent();
}
private string getAStandardLoggerMethodName() {
// log level names used in RFC5424, `npm`, `console`
result = "crit" or
result = "debug" or
result = "error" or
result = "emerg" or
result = "fatal" or
result = "info" or
result = "log" or
result = "notice" or
result = "silly" or
result = "trace" or
result = "warn"
}
/**
* Provides classes for working the builtin NodeJS/Browser `console`.
*/
private module Console {
/**
* Gets a data flow source node for the console library.
*/
private DataFlow::SourceNode console() {
result = DataFlow::moduleImport("console") or
result = DataFlow::globalVarRef("console")
}
/**
* A call to the console logging mechanism.
*/
class ConsoleLoggerCall extends LoggerCall {
string name;
ConsoleLoggerCall() {
(
name = getAStandardLoggerMethodName() or
name = "assert"
) and
this = console().getAMethodCall(name)
}
override DataFlow::Node getAMessageComponent() {
if name = "assert" then
result = getArgument([1..getNumArgument()])
else
result = getAnArgument()
}
}
}
/**
* Provides classes for working with [loglevel](https://github.com/pimterry/loglevel).
*/
private module Loglevel {
/**
* A call to the loglevel logging mechanism.
*/
class LoglevelLoggerCall extends LoggerCall {
LoglevelLoggerCall() {
this = DataFlow::moduleMember("loglevel", getAStandardLoggerMethodName()).getACall()
}
override DataFlow::Node getAMessageComponent() {
result = getAnArgument()
}
}
}
/**
* Provides classes for working with [winston](https://github.com/winstonjs/winston).
*/
private module Winston {
/**
* A call to the winston logging mechanism.
*/
class WinstonLoggerCall extends LoggerCall, DataFlow::MethodCallNode {
WinstonLoggerCall() {
this = DataFlow::moduleMember("winston", "createLogger").getACall().getAMethodCall(getAStandardLoggerMethodName())
}
override DataFlow::Node getAMessageComponent() {
if getMethodName() = "log" then
result = getOptionArgument(0, "message")
else
result = getAnArgument()
}
}
}
/**
* Provides classes for working with [log4js](https://github.com/log4js-node/log4js-node).
*/
private module log4js {
/**
* A call to the log4js logging mechanism.
*/
class Log4jsLoggerCall extends LoggerCall {
Log4jsLoggerCall() {
this = DataFlow::moduleMember("log4js", "getLogger").getACall().getAMethodCall(getAStandardLoggerMethodName())
}
override DataFlow::Node getAMessageComponent() {
result = getAnArgument()
}
}
}

View File

@@ -0,0 +1,17 @@
| tst.js:3:1:3:26 | console ... ", arg) | tst.js:3:13:3:20 | "msg %s" |
| tst.js:3:1:3:26 | console ... ", arg) | tst.js:3:23:3:25 | arg |
| tst.js:4:1:4:28 | console ... ", arg) | tst.js:4:15:4:22 | "msg %s" |
| tst.js:4:1:4:28 | console ... ", arg) | tst.js:4:25:4:27 | arg |
| tst.js:5:1:5:28 | console ... ", arg) | tst.js:5:15:5:22 | "msg %s" |
| tst.js:5:1:5:28 | console ... ", arg) | tst.js:5:25:5:27 | arg |
| tst.js:7:1:7:34 | require ... ", arg) | tst.js:7:21:7:28 | "msg %s" |
| tst.js:7:1:7:34 | require ... ", arg) | tst.js:7:31:7:33 | arg |
| tst.js:9:1:9:38 | require ... ", arg) | tst.js:9:25:9:32 | "msg %s" |
| tst.js:9:1:9:38 | require ... ", arg) | tst.js:9:35:9:37 | arg |
| tst.js:11:1:11:73 | require ... other) | tst.js:11:50:11:63 | "msg with arg" |
| tst.js:12:1:12:53 | require ... ", arg) | tst.js:12:40:12:47 | "msg %s" |
| tst.js:12:1:12:53 | require ... ", arg) | tst.js:12:50:12:52 | arg |
| tst.js:14:1:14:48 | require ... ", arg) | tst.js:14:35:14:42 | "msg %s" |
| tst.js:14:1:14:48 | require ... ", arg) | tst.js:14:45:14:47 | arg |
| tst.js:16:1:16:35 | console ... ", arg) | tst.js:16:22:16:29 | "msg %s" |
| tst.js:16:1:16:35 | console ... ", arg) | tst.js:16:32:16:34 | arg |

View File

@@ -0,0 +1,4 @@
import javascript
from LoggerCall log
select log, log.getAMessageComponent()

View File

@@ -0,0 +1,16 @@
var requiredConsole = require("console");
console.log("msg %s", arg);
console.fatal("msg %s", arg);
console.debug("msg %s", arg);
requiredConsole.log("msg %s", arg);
require("loglevel").log("msg %s", arg);
require("winston").createLogger().log({ message: "msg with arg" }, other);
require("winston").createLogger().info("msg %s", arg);
require("log4js").getLogger().log("msg %s", arg);
console.assert(true, "msg %s", arg);