Weakness reference
CWE-317

Cleartext Storage of Sensitive Information in GUI

This weakness occurs when an application displays sensitive data—such as passwords, API keys, credit card numbers, or authentication tokens—in plain, readable…

01Summary

This weakness occurs when an application displays sensitive data—such as passwords, API keys, credit card numbers, or authentication tokens—in plain, readable text on the screen instead of masking or hiding it. Anyone with physical or remote visual access to the screen can read this information directly, bypassing the need for technical exploitation. It is a simple but often overlooked vulnerability that can lead to immediate credential compromise.

02How It Happens

Developers sometimes prioritize usability or debugging convenience over security when designing user interfaces. A form field intended for password entry may lack a masking mechanism (such as replacing characters with dots or asterisks), or sensitive data may be displayed in logs, error messages, or status windows without obfuscation. In some cases, the data is stored in memory or cached in a way that remains visible if the screen is left unattended, or it may be captured in screenshots or screen recordings. The underlying assumption—that physical or visual access to the screen is inherently trusted—is often incorrect in shared workspaces, remote sessions, or environments where screen sharing occurs.

03Real-World Impact

Cleartext storage of sensitive information in the GUI can lead to immediate credential theft, account takeover, or unauthorized access to protected resources. An attacker with visual access—whether through shoulder surfing, screen sharing, screenshots, or surveillance—can obtain passwords or tokens without needing to exploit the application's code. In regulated industries (finance, healthcare, government), this violation can trigger compliance failures and significant penalties. The impact is particularly severe in shared or public environments, remote work settings, or situations where screen recordings are made for training or support purposes.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import tkinter as tk

root = tk.Tk()
root.title("Login")

tk.Label(root, text="Username:").pack()
username_entry = tk.Entry(root)
username_entry.pack()

tk.Label(root, text="Password:").pack()
password_entry = tk.Entry(root)  # No show parameter — text is visible
password_entry.pack()

def login():
    pwd = password_entry.get()
    print(f"Logging in with password: {pwd}")  # Logs cleartext

tk.Button(root, text="Login", command=login).pack()
root.mainloop()

Why it's vulnerable:
The password entry field has no masking mechanism, so characters typed are visible on screen. Additionally, the password is logged in cleartext, creating a persistent record.

Fixed pattern
import tkinter as tk

root = tk.Tk()
root.title("Login")

tk.Label(root, text="Username:").pack()
username_entry = tk.Entry(root)
username_entry.pack()

tk.Label(root, text="Password:").pack()
password_entry = tk.Entry(root, show="*")  # Mask characters with asterisks
password_entry.pack()

def login():
    pwd = password_entry.get()
    # Do not log the password; log only success/failure
    print("Login attempt processed")

tk.Button(root, text="Login", command=login).pack()
root.mainloop()
Vulnerable pattern
<?php
// Display user's API key in a form field for "convenience"
$api_key = $_SESSION['api_key'];
?>
<form>
    <label>Your API Key:</label>
    <input type="text" value="<?php echo $api_key; ?>" />
    <!-- Key is visible in plaintext on screen and in HTML source -->
</form>

Why it's vulnerable:
The API key is rendered directly in the HTML input field as a visible value attribute, making it readable in the browser, in page source, and in any screenshot or recording.

Fixed pattern
<?php
// Never display the full API key; show only a masked version
$api_key = $_SESSION['api_key'];
$masked = substr($api_key, 0, 4) . str_repeat('*', strlen($api_key) - 8) . substr($api_key, -4);
?>
<form>
    <label>Your API Key (masked):</label>
    <input type="text" value="<?php echo htmlspecialchars($masked); ?>" readonly />
    <p><small>For security, the full key is not displayed. Use the "Copy" button to copy it securely.</small></p>
</form>

05Prevention Checklist

Mask password and sensitive input fields
using the type="password" attribute in HTML or equivalent masking in desktop/mobile UIs (show="*" in Tkinter, secureTextEntry in iOS, etc.).
Never log or display full sensitive values
(passwords, tokens, keys, PII) in error messages, status windows, or debug output; log only success/failure or sanitized identifiers.
Use read-only or copy-to-clipboard mechanisms
for displaying sensitive data that users need to reference, rather than leaving it editable and visible.
Clear sensitive data from memory and UI
after use; do not leave passwords or tokens in form fields or cached in recent-input lists.
Audit UI mockups and screenshots
during design and code review to ensure no sensitive data is visible in normal operation or error states.
Train developers and QA
on the risks of cleartext display and the importance of masking, especially in shared or remote work environments.

06Signs You May Already Be Affected

Review your application's login forms, settings pages, and error messages for any fields that display passwords, API keys, tokens, or PII in readable text. Check logs and debug output for instances where sensitive data is written in cleartext. If you use screen recording or session replay tools, verify that they do not capture password fields or other masked inputs—many such tools have built-in redaction features that should be enabled.

07Related Recent Vulnerabilities