Full Report
CSS can style visited links differently than unvisited links. From a security perspective, this is a problem because a web page can review a user's complete history this way for other sites. This post provides a summary of the problem and proposes a solution. Website authors can use the getComputedStyle function to determine if a link has been visited or not. An easy way to fix this would be to make this API lie. In practice, this approach doesn't work because the CSS styling itself can vary, including colors, spacing, and other elements. To fix the above issue, a limitation would need to be put in place to limit the ability to style pages on whether links were visitd or not. Many CSS selectors will always act as if they've been visited. Additionally, the CSS properties applied to links should be limited to a few select options. A few limitations of this approach are discussed, highlighting the importance of the mitigating threat model for these types of features. First, this is NOT intended to resolve attacks that require user interaction via clicks. Second, fine-grained timing attacks - they hope this prevents most practical ones. Finally, this doesn't intend to avoid browser cache-based attacks. Overall, a great post on a proposed browser mitigation for a well-known attack vector while keeping as much functionality as possible.
Analysis Summary
# Vulnerability: Browser History Leakage via CSS :visited Pseudo-Class
## CVE Details
- **CVE ID**: Not explicitly named in the article (Historically associated with **CVE-2010-0654**)
- **CVSS Score**: 5.0 (Medium - Estimated)
- **CWE**: CWE-200: Information Exposure (Specifically History Sniffing)
## Affected Systems
- **Products**: All major web browsers (at the time of the report), specifically those using the Gecko layout engine (Firefox).
- **Versions**: All versions prior to the implementation of the proposed privacy patches (Firefox 4 and later).
- **Configurations**: Default browser configurations where `:visited` link styling is enabled.
## Vulnerability Description
The flaw exists because CSS allows web authors to style visited links differently from unvisited links (e.g., changing colors). Historically, browsers allowed scripts to programmatically query these styles via the `getComputedStyle()` API. This allowed malicious websites to:
1. Create a hidden list of thousands of popular URLs.
2. Use JavaScript to check if the browser rendered them as "visited" or "unvisited."
3. Exfiltrate the user's browsing history without user interaction or consent.
Beyond simple script-based checks, the vulnerability also allowed for "layout-based" side channels, where different styles for visited links (like font size or background images) could change the page's layout or trigger network requests, signaling the link's status to the server.
## Exploitation
- **Status**: Exploited in the wild / PoC available.
- **Complexity**: Low.
- **Attack Vector**: Network (Web-based).
## Impact
- **Confidentiality**: Medium/High (Complete disclosure of a user's browsing history to any website they visit).
- **Integrity**: None.
- **Availability**: None.
## Remediation
### Patches
- **Mozilla Gecko/Firefox**: Patches were implemented in Firefox 4 to strictly limit `:visited` styling.
- **Chromium/WebKit**: Similar logic was adopted across all modern browser engines.
### Workarounds
- **Manual Configuration**: In legacy Firefox (3.5+), users could set `layout.css.visited_links_enabled` to `false` in `about:config`.
- **Private Browsing**: Use "Incognito" or "Private" modes, which do not persist history for these selectors to query.
## Detection
### Indicators of Compromise
- High-volume, rapid creation of invisible `<a>` tags via JavaScript.
- Use of `getComputedStyle` on link elements immediately after page load.
### Detection Methods and Tools
- **Browser Developer Tools**: Inspecting network logs for unusual requests triggered by CSS properties or scripts querying link colors.
- **Privacy Badger / uBlock Origin**: These tools often block known history-sniffing scripts.
## References
- hxxps://bugzilla.mozilla.org/show_bug.cgi?id=147777
- hxxps://blog.mozilla.org/security/2010/03/31/plugging-the-css-history-leak/
- hxxps://dbaron.org/mozilla/visited-privacy