Sensitive information logged via print / debugPrint / log
ID |
dart.privacy.sensitive_information_logging |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
medium |
Remediation Effort |
low |
Resource |
Privacy |
Language |
Dart |
Description
Sensitive information (token, password, secret, API key, JWT, PIN, email, phone, SSN, DOB) is logged via print, debugPrint, log, or developer.log. On Android the output reaches logcat (readable by other apps with READ_LOGS, adb logcat, and surfaces in crash dumps); on iOS it reaches Console / OSLog.
Rationale
Mobile log output is not a private channel. Specifically:
-
Android: applications targeting API < 16 (or with the
READ_LOGSpermission, which most security tools have) can read all logcat output. Crash reporters frequently scoop up recent log lines and ship them to third-party services (Crashlytics, Sentry, Bugsnag), where the secret is then persisted off-device and accessible to anyone with dashboard access. -
iOS:
developer.log/os_logcalls reach the system log, which is accessible from the Console app over USB and from diagnostic exports the user uploads with the app’s crash reports. -
Both: developer-mode devices stream logs over
adb logcat/idevicesyslog, often in environments where the user has handed the device to an IT-support technician.
The rule catches bare identifiers with secret-suggesting names
(print(token)), $-interpolation of those identifiers in
string literals (print("token=$token")), and label-style
logging (print("password: $value")).
The following code illustrates a vulnerable pattern detected by this rule:
class LeakyLogs {
void bareIdentifiers(String token, String password, String apiKey,
String jwt, String email, String phone) {
// VULNERABLE: Sensitive information logged via print / debugPrint / log
print(token);
// VULNERABLE: Sensitive information logged via print / debugPrint / log
print(password);
debugPrint(apiKey);
// VULNERABLE: Sensitive information logged via print / debugPrint / log
debugPrint(jwt);
// VULNERABLE: Sensitive information logged via print / debugPrint / log
developer.log(email);
// VULNERABLE: Sensitive information logged via print / debugPrint / log
developer.log(phone);
}
}
Remediation
Never log credentials, PII, or any value the user expects to be
confidential. Redact at the boundary — mask all but the last few
characters, hash the value, or drop the log line entirely. Use
kDebugMode from package:flutter/foundation.dart to gate
verbose diagnostics out of release builds.
// Vulnerable
print('Got token: $token');
debugPrint(password);
// Fixed: redact + gate to debug builds
final masked = '${token.substring(0, 4)}…';
if (kDebugMode) {
debugPrint('Got token: $masked');
}
References
-
OWASP Top 10 2025 - A09 : Security Logging and Alerting Failures.
-
Talsec — OWASP Mobile Top 10 for Flutter M6 — Inadequate privacy controls in Flutter and Dart
-
kDebugMode — Flutter foundation library — Compile-time flag for gating diagnostic logging out of release builds
-
Dart linter — avoid_print — First-party lint discouraging bare
printin shipped code