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_LOGS permission, 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_log calls 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');
}

Configuration

This detector does not need any configuration.

References

© 2026 Xygeni. All rights reserved