This weakness occurs when an application displays sensitive data—such as passwords, API keys, credit card numbers, or authentication tokens—in plain, readable…
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.