Create getAValueFormattedMessageComponent

This commit is contained in:
Owen Mansel-Chan
2025-03-20 14:48:24 +00:00
parent 05a94807e1
commit f944ff4d78
5 changed files with 22 additions and 10 deletions

View File

@@ -355,13 +355,17 @@ module RegexpReplaceFunction {
* extend `LoggerCall::Range` instead.
*/
class LoggerCall extends DataFlow::Node instanceof LoggerCall::Range {
/** Gets a node that is a part of the logged message. */
DataFlow::Node getAMessageComponent() { result = super.getAMessageComponent() }
/**
* Gets a node whose value is a part of the logged message. Note that
* components corresponding to the format specifier "%T" are excluded as
* Gets a node whose value is a part of the logged message.
*
* Components corresponding to the format specifier "%T" are excluded as
* their type is logged rather than their value.
*/
DataFlow::Node getAMessageComponent() {
result = super.getAMessageComponent() and
DataFlow::Node getAValueFormattedMessageComponent() {
result = this.getAMessageComponent() and
not exists(string formatSpecifier |
formatSpecifier.regexpMatch("%[^%]*T") and
result = this.(StringOps::Formatting::StringFormatCall).getOperand(_, formatSpecifier)

View File

@@ -40,7 +40,7 @@ module CleartextLogging {
* An argument to a logging mechanism.
*/
class LoggerSink extends Sink {
LoggerSink() { this = any(LoggerCall log).getAMessageComponent() }
LoggerSink() { this = any(LoggerCall log).getAValueFormattedMessageComponent() }
}
/**

View File

@@ -35,7 +35,7 @@ module LogInjection {
/** An argument to a logging mechanism. */
class LoggerSink extends Sink {
LoggerSink() { this = any(LoggerCall log).getAMessageComponent() }
LoggerSink() { this = any(LoggerCall log).getAValueFormattedMessageComponent() }
}
/**

View File

@@ -138,7 +138,9 @@ predicate privateUrlFlowsToAuthCodeUrlCall(DataFlow::CallNode call) {
module FlowToPrintConfig implements DataFlow::ConfigSig {
additional predicate isSinkCall(DataFlow::Node sink, DataFlow::CallNode call) {
exists(LoggerCall logCall | call = logCall | sink = logCall.getAMessageComponent())
exists(LoggerCall logCall | call = logCall |
sink = logCall.getAValueFormattedMessageComponent()
)
}
predicate isSource(DataFlow::Node source) { source = any(AuthCodeUrl m).getACall().getResult() }

View File

@@ -4,14 +4,20 @@ import ModelValidation
import utils.test.InlineExpectationsTest
module LoggerTest implements TestSig {
string getARelevantTag() { result = "logger" }
string getARelevantTag() { result = ["type-logger", "logger"] }
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(LoggerCall log |
log.getLocation() = location and
element = log.toString() and
value = log.getAMessageComponent().toString() and
tag = "logger"
(
value = log.getAValueFormattedMessageComponent().toString() and
tag = "logger"
or
value = log.getAMessageComponent().toString() and
not value = log.getAValueFormattedMessageComponent().toString() and
tag = "type-logger"
)
)
}
}