Weakness reference
CWE-525

Use of Web Browser Cache Containing Sensitive Information

This weakness occurs when a web application stores sensitive data passwords, authentication tokens, personal information, financial details in the browser's…

01Summary

This weakness occurs when a web application stores sensitive data (passwords, authentication tokens, personal information, financial details) in the browser's cache without proper controls. Once cached, this data may persist on disk long after the user closes their browser, making it accessible to anyone with physical or logical access to the device — particularly dangerous on shared computers, public terminals, or devices that are later sold or repurposed.

02How It Happens

Web browsers automatically cache HTTP responses to improve performance and reduce bandwidth. By default, most browsers cache responses marked with standard cache headers, including pages containing sensitive information. Developers often overlook cache directives when building authentication flows, account pages, or forms that handle passwords or tokens. The browser stores this cached content in a local directory on the user's machine, where it can be recovered even after the session ends — either through the browser's cache viewer, file system access, or forensic tools. The weakness is compounded on shared devices where multiple users access the same machine.

03Real-World Impact

An attacker with access to a shared computer (a library terminal, internet café, or office workstation) can retrieve cached pages containing login credentials, session tokens, or personal data. This enables account takeover, identity theft, or unauthorized access to sensitive accounts. On corporate networks, cached financial or health information could lead to compliance violations (HIPAA, PCI-DSS, GDPR). Even after a user believes their session is private, their sensitive data remains recoverable from the device's storage.

04Vulnerable & Fixed Patterns

Vulnerable pattern
from flask import Flask, render_template, request

app = Flask(__name__)

@app.route('/account')
def account_page():
    user_data = {
        'username': request.args.get('user'),
        'api_token': request.args.get('token'),
        'credit_card': '****1234'
    }
    return render_template('account.html', data=user_data)

Why it's vulnerable:
The response is returned without cache-control headers, so the browser caches the page containing the API token and user data. An attacker with device access can retrieve this cached HTML file.

Fixed pattern
from flask import Flask, render_template, request, make_response

app = Flask(__name__)

@app.route('/account')
def account_page():
    user_data = {
        'username': request.args.get('user'),
        'api_token': request.args.get('token'),
        'credit_card': '****1234'
    }
    response = make_response(render_template('account.html', data=user_data))
    response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0'
    response.headers['Pragma'] = 'no-cache'
    response.headers['Expires'] = '0'
    return response
Vulnerable pattern
<?php
session_start();
$user_token = $_GET['token'];
$account_data = [
    'username' => $_SESSION['user'],
    'token' => $user_token,
    'balance' => get_account_balance()
];
?>
<html>
<body>
    <h1>Account: <?php echo $account_data['username']; ?></h1>
    <p>Token: <?php echo $account_data['token']; ?></p>
    <p>Balance: $<?php echo $account_data['balance']; ?></p>
</body>
</html>

Why it's vulnerable:
No cache-control headers are sent, so the browser caches the entire page including the session token and account balance.

Fixed pattern
<?php
session_start();
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
header('Expires: 0');

$user_token = $_GET['token'];
$account_data = [
    'username' => $_SESSION['user'],
    'token' => $user_token,
    'balance' => get_account_balance()
];
?>
<html>
<body>
    <h1>Account: <?php echo htmlspecialchars($account_data['username']); ?></h1>
    <p>Token: <?php echo htmlspecialchars($account_data['token']); ?></p>
    <p>Balance: $<?php echo htmlspecialchars($account_data['balance']); ?></p>
</body>
</html>

05Prevention Checklist

Add Cache-Control: no-store, no-cache, must-revalidate, max-age=0 headers to all responses containing sensitive data (login pages, account dashboards, payment forms, admin panels).
Include Pragma: no-cache and Expires: 0 headers for compatibility with older browsers and proxies.
Never pass sensitive data (tokens, passwords, PII) in URL query parameters; use POST requests with secure session cookies instead.
Configure session cookies with HttpOnly and Secure flags to prevent JavaScript access and enforce HTTPS-only transmission.
Test your application in a private/incognito browser window and verify that sensitive pages do not appear in the browser's cache history.
Document which pages handle sensitive data and ensure cache headers are applied consistently across your application.

06Signs You May Already Be Affected

Check your browser's cache directory (typically ~/.cache/ on Linux, ~/Library/Caches/ on macOS, or %LOCALAPPDATA%\Cache\ on Windows) for HTML files from your application's sensitive pages. If you find cached versions of login pages, account dashboards, or payment forms, your application is not properly preventing cache storage. Review your web server or application logs for missing or incorrect cache-control headers on sensitive endpoints.

07Related Recent Vulnerabilities