Skip to content

Vulnerability fix proposal: Private Key Passphrase Stored in Shared and others.#17

Open
Alb4don wants to merge 2 commits into
eddieoz:mainfrom
Alb4don:main
Open

Vulnerability fix proposal: Private Key Passphrase Stored in Shared and others.#17
Alb4don wants to merge 2 commits into
eddieoz:mainfrom
Alb4don:main

Conversation

@Alb4don
Copy link
Copy Markdown

@Alb4don Alb4don commented May 14, 2026

  • Affected component: content.js, setSessionPassphrase() (lines 329–331), getSessionPassphrase() (lines 323–326), and the message listener (lines 619–625).

  • The extension stored the user's private key password directly in sessionStorage. Although Chrome content scripts run in an isolated JavaScript environment, the DOM storage APIs sessionStorage and localStorage are still shared with the host page.

  • This means that everything stored by the content script could be read/retrieved by any script (including third-party scripts) running on twitter.com, x.com, or web.whatsapp.com.

apassword

What made this more interesting was the persistence behavior. After a page refresh, the passphrase was still there and when the user clicked any link that triggered window.open() which Twitter does constantly the new tab inherited the full sessionStorage of the parent, passphrase included.

passss
  • We also confirmed that the AES-GCM encryption used for public tweets derived its key entirely from the GPG fingerprint .

  • And The private keys themselves were stored in plaintext inside chrome.storage.local, persisted to disk. Combined with the passphrase sitting in sessionStorage.

Alb4don added 2 commits May 14, 2026 06:56
…nd others.

sessionStorage is readable by any JavaScript running in the same origin, including injected scripts. The passphrase was stored in cleartext. This pull fixes the problems. 

- The passphrase is now wrapped with AES-GCM before storage. A random 32-byte salt is used to derive a per-session wrapping key via HKDF (SHA-256) using crypto.subtle. 

- The salt + IV + ciphertext blob is base64-encoded and stored as sessionPassphraseBlob. 

- The raw passphrase never touches sessionStorage. 

- The resetPassphrase handler now clears sessionPassphraseBlob instead of the old sessionPassphrase key.
…ifier strings.

- A createKeyRow() helper and a createTextCell() helper are introduced. 

- All table rows are now built exclusively through the DOM API (createElement, textContent, dataset). 

- No string interpolation into HTML is used anywhere in key table rendering.
Copy link
Copy Markdown
Owner

@eddieoz eddieoz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution!

Please revert the deletion of the original documenting comments. Documenting comments are essential for explaining the why behind the code for future maintainers, and we need to keep them intact.

Additionally, please update your new comments to remove the FIX: prefix and format them as standard, clean documenting comments.

Why we avoid FIX: prefixes in the codebase:

  • Noise vs. Signal: While FIX: is useful in temporary git commit messages or local TODOs, leaving it permanently in the source code adds unnecessary text that litters the codebase over time.
  • The "Trashing" Effect: If every developer tags their changes with prefixes like FIX:, CHANGED:, or PATCH:, the code quickly becomes crowded with historical meta-text that doesn't add value to the actual logic.
  • Clean Code Principle: A good code comment should cleanly describe what the code does or why it exists, without needing historical context markers. The exact history of who fixed what is already perfectly preserved in the Git history.

Example of what to do:

❌ Avoid:

// FIX: Adjusted the timeout buffer to prevent race conditions on slow connections

  • can you change it to:*
// Adjust the timeout buffer to prevent race conditions on slow connections

Once the original documentation is restored and the new comments are cleaned up, this will be good to go!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants