Files
codeql/swift/ql/test/query-tests/Security/CWE-312/cleartextLoggingTest.swift
Tony Torralba 49a41c98ee Test that hashed passwords are 'safe' to log
This doesn't seem completely right, but the heuristic approach we have regarding sensitive expressions has to draw the line somewhere.
2023-01-09 18:01:07 +01:00

159 lines
9.3 KiB
Swift

// --- stubs ---
func NSLog(_ format: String, _ args: CVarArg...) {}
func NSLogv(_ format: String, _ args: CVaListPointer) {}
func getVaList(_ args: [CVarArg]) -> CVaListPointer { return CVaListPointer(_fromUnsafeMutablePointer: UnsafeMutablePointer(bitPattern: 0)!) }
struct OSLogType : RawRepresentable {
static let `default` = OSLogType(rawValue: 0)
let rawValue: UInt8
init(rawValue: UInt8) { self.rawValue = rawValue}
}
struct OSLogStringAlignment {
static var none = OSLogStringAlignment()
}
enum OSLogIntegerFormatting { case decimal }
enum OSLogInt32ExtendedFormat { case none }
enum OSLogFloatFormatting { case fixed }
enum OSLogBoolFormat { case truth }
struct OSLogPrivacy {
enum Mask { case none }
static var auto = OSLogPrivacy()
static var `private` = OSLogPrivacy()
static var `public` = OSLogPrivacy()
static var sensitive = OSLogPrivacy()
static func auto(mask: OSLogPrivacy.Mask) -> OSLogPrivacy { return .auto }
static func `private`(mask: OSLogPrivacy.Mask) -> OSLogPrivacy { return .private }
static func `sensitive`(mask: OSLogPrivacy.Mask) -> OSLogPrivacy { return .sensitive }
}
struct OSLogInterpolation : StringInterpolationProtocol {
typealias StringLiteralType = String
init(literalCapacity: Int, interpolationCount: Int) {}
func appendLiteral(_: Self.StringLiteralType) {}
mutating func appendInterpolation(_ argumentString: @autoclosure @escaping () -> String, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto) {}
mutating func appendInterpolation(_ argumentString: @autoclosure @escaping () -> String, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto, attributes: String) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Int, format: OSLogIntegerFormatting = .decimal, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Int8, format: OSLogIntegerFormatting = .decimal, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Int16, format: OSLogIntegerFormatting = .decimal, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Int32, format: OSLogInt32ExtendedFormat, privacy: OSLogPrivacy = .auto) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Int32, format: OSLogInt32ExtendedFormat, privacy: OSLogPrivacy = .auto, attributes: String) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Int32, format: OSLogIntegerFormatting = .decimal, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Int64, format: OSLogIntegerFormatting = .decimal, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> UInt, format: OSLogIntegerFormatting = .decimal, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> UInt8, format: OSLogIntegerFormatting = .decimal, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> UInt16, format: OSLogIntegerFormatting = .decimal, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> UInt32, format: OSLogIntegerFormatting = .decimal, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> UInt64, format: OSLogIntegerFormatting = .decimal, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Double, format: OSLogFloatFormatting = .fixed, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Double, format: OSLogFloatFormatting = .fixed, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto, attributes: String) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Float,format: OSLogFloatFormatting = .fixed, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto) {}
mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Float, format: OSLogFloatFormatting = .fixed, align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto, attributes: String) {}
mutating func appendInterpolation(_ boolean: @autoclosure @escaping () -> Bool, format: OSLogBoolFormat = .truth, privacy: OSLogPrivacy = .auto) {}
}
struct OSLogMessage : ExpressibleByStringInterpolation {
typealias StringInterpolation = OSLogInterpolation
typealias StringLiteralType = String
typealias ExtendedGraphemeClusterLiteralType = String
typealias UnicodeScalarLiteralType = String
init(stringInterpolation: OSLogInterpolation) {}
init(stringLiteral: String) {}
init(extendedGraphemeClusterLiteral: String) {}
init(unicodeScalarLiteral: String) {}
}
struct Logger {
func log(_ message: OSLogMessage) {}
func log(level: OSLogType, _ message: OSLogMessage) {}
func notice(_: OSLogMessage) {}
func debug(_: OSLogMessage) {}
func trace(_: OSLogMessage) {}
func info(_: OSLogMessage) {}
func error(_: OSLogMessage) {}
func warning(_: OSLogMessage) {}
func fault(_: OSLogMessage) {}
func critical(_: OSLogMessage) {}
}
// --- tests ---
func test1(password: String, passwordHash : String) {
print(password) // $ MISSING: hasCleartextLogging=87
print(password, separator: "") // $ MISSING: $ hasCleartextLogging=88
print("", separator: password) // $ hasCleartextLogging=89
print(password, separator: "", terminator: "") // $ MISSING: hasCleartextLogging=90
print("", separator: password, terminator: "") // $ hasCleartextLogging=91
print("", separator: "", terminator: password) // $ hasCleartextLogging=92
print(passwordHash) // Safe
NSLog(password) // $ hasCleartextLogging=95
NSLog("%@", password as! CVarArg) // $ MISSING: hasCleartextLogging=96
NSLog("%@ %@", "" as! CVarArg, password as! CVarArg) // $ MISSING: hasCleartextLogging=97
NSLog("\(password)") // $ hasCleartextLogging=98
NSLogv("%@", getVaList([password as! CVarArg])) // $ MISSING: hasCleartextLogging=99
NSLogv("%@ %@", getVaList(["" as! CVarArg, password as! CVarArg])) // $ MISSING: hasCleartextLogging=100
NSLog(passwordHash) // SAfe
NSLogv("%@", getVaList([passwordHash as! CVarArg])) // Safe
let bankAccount: Int = 0
let log = Logger()
// These MISSING test cases will be fixed when we properly generate the CFG around autoclosures.
log.log("\(password)") // Safe
log.log("\(password, privacy: .auto)") // Safe
log.log("\(password, privacy: .private)") // Safe
log.log("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=110
log.log("\(passwordHash, privacy: .public)") // Safe
log.log("\(password, privacy: .sensitive)") // Safe
log.log("\(bankAccount)") // $ MISSING: hasCleartextLogging=113
log.log("\(bankAccount, privacy: .auto)") // $ MISSING: hasCleartextLogging=114
log.log("\(bankAccount, privacy: .private)") // Safe
log.log("\(bankAccount, privacy: .public)") // $ MISSING: hasCleartextLogging=116
log.log("\(bankAccount, privacy: .sensitive)") // Safe
log.log(level: .default, "\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=118
log.trace("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=119
log.trace("\(passwordHash, privacy: .public)") // Safe
log.debug("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=121
log.debug("\(passwordHash, privacy: .public)") // Safe
log.info("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=123
log.info("\(passwordHash, privacy: .public)") // Safe
log.notice("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=125
log.notice("\(passwordHash, privacy: .public)") // Safe
log.warning("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=127
log.warning("\(passwordHash, privacy: .public)") // Safe
log.error("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=129
log.error("\(passwordHash, privacy: .public)") // Safe
log.critical("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=131
log.critical("\(passwordHash, privacy: .public)") // Safe
log.fault("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=133
log.fault("\(passwordHash, privacy: .public)") // Safe
}
class MyClass {
var harmless = "abc"
var password = "123"
}
func getPassword() -> String { return "" }
func doSomething(password: String) { }
func test3(x: String) {
// alternative evidence of sensitivity...
NSLog(x) // $ MISSING: hasCleartextLogging=148
doSomething(password: x);
NSLog(x) // $ hasCleartextLogging=149
let y = getPassword();
NSLog(y) // $ hasCleartextLogging=152
let z = MyClass()
NSLog(z.harmless) // Safe
NSLog(z.password) // $ hasCleartextLogging=157
}