Browser Extension
Argon ships a Manifest V3 browser extension that detects login forms, injects the Argon logo into input fields, and presents an inline credential picker dropdown — all without leaving the page.How It Works
The extension has three layers:| Component | File | Purpose |
|---|---|---|
| Content Script | content/autofill.js | Runs on every page. Detects login forms, injects Argon icons, renders the inline dropdown, and fills credentials. |
| Service Worker | background/service-worker.js | Manages session state, communicates with the Argon server via gRPC-Web, handles URL matching and credential retrieval. |
| Popup | popup/popup.html | Full vault access when the toolbar icon is clicked — login, search, browse credentials, generate passwords. |
Inline Autofill
When the extension detects a login form on a page, it injects the Argon logo at the end of each input field (username and password). Clicking the logo opens an inline dropdown directly below the field — no popup, no redirect.Form Detection
The content script identifies login forms through multiple strategies:- Form-based — Scans all
<form>elements forinput[type="password"]fields, then finds the associated username field. - Standalone — Detects
input[type="password"]fields not inside a<form>(common in SPAs). - Autocomplete hints — Prioritizes fields with
autocomplete="username",autocomplete="email", orautocomplete="new-password". - Heuristic fallback — Searches by
name,id, andtypeattributes (email,user,login).
Username Field Priority
When multiple candidate fields exist, the extension picks the best match in order:Icon Injection
Each detected input field gets an Argon logo icon positioned inside the field’s right padding:- The icon uses the
argon.pnglogo from the extension’sicons/directory, loaded viachrome.runtime.getURL(). - Styled with the Argon purple gradient (
#cb85ffto#6c3aff). - Subtle on idle (65% opacity), full brightness on hover.
- Injected inside a closed Shadow DOM to prevent page CSS from interfering and page JS from reading credential data.
Credential Picker Dropdown
Clicking the icon opens a dropdown below the input field:- URL matching — Only credentials with a stored URL matching the current page are shown.
- Search — The search input filters by entry name, username, or URL (client-side, no server calls).
- Click to fill — Selecting an item decrypts the credential and fills both username and password fields.
- Keyboard navigation — Arrow keys to move, Enter to select, Escape to close.
URL Matching
The service worker matches stored credential URLs against the current page:Shadow DOM Isolation
All injected UI (icons and dropdown) lives inside a closed Shadow DOM:- Page CSS cannot leak in — The extension’s styling is completely isolated from the page.
- Extension CSS cannot leak out — Argon’s purple theme doesn’t affect the page’s appearance.
- Page JS cannot read credentials — Closed shadow roots are inaccessible to
document.querySelector()or any DOM traversal from the page.
Framework-Aware Filling
Modern web apps use React, Vue, Angular, and other frameworks that don’t respond to simpleinput.value = "..." assignments. Argon’s fill logic uses the native property setter and dispatches all events frameworks listen for:
onChange, Vue’s v-model, Angular’s ngModel, and any other framework’s change detection.
SPA Navigation
Single-page applications change routes without full page reloads. The extension handles this with:- MutationObserver — Watches for DOM changes (new form elements injected) and re-scans with debouncing (200ms).
- popstate / hashchange listeners — Re-scans on SPA route changes.
- Dropdown cleanup — Open dropdowns are closed on navigation to prevent stale UI.
Authentication
The extension authenticates to the Argon server the same way the desktop app does:Password Login
- User enters username and master password in the popup.
- Extension sends
GetChallenge(username)to the server. - Derives
auth_keyfrom password + salt using Argon2id. - Computes
verifier = SHA-256(auth_key), thenproof = HMAC-SHA256(verifier, challenge_nonce). - Sends
Login(username, proof, challenge_id). - Server verifies proof against stored verifier — returns session token.
Passkey / YubiKey Login
- User clicks “Sign in with Passkey” in the popup.
- Extension calls
BeginAuthentication(username)to get WebAuthn options. - Browser prompts for the security key (YubiKey tap, fingerprint, etc.).
- Extension sends the signed assertion to
FinishAuthentication. - Server verifies and returns session token.
Session Management
- Sessions expire after a configurable timeout (default 15 minutes of inactivity).
- A
chrome.alarmstimer checks inactivity every minute. - On lock, the session token is cleared and the popup shows the login screen.
Popup Features
The toolbar popup provides full vault access when the inline autofill isn’t sufficient:- Credential search — Search across all vaults by name or username.
- Password generator — Customizable length, character sets, with copy-to-clipboard.
- Settings — Server URL configuration, options page link.
- Lock — Manual vault lock.
Permissions
| Permission | Purpose |
|---|---|
activeTab | Access the current tab’s URL for credential matching |
storage | Persist server URL and extension settings |
alarms | Auto-lock timer |
webRequest | Detect navigation events for SPA handling |
<all_urls> (host) | Content script injection on all pages for form detection |
Security Considerations
- Credentials never stored in extension — Decrypted usernames and passwords are received from the service worker, passed directly to
fillCredentials(), and immediately discarded. They are not saved to variables, DOM attributes, local storage, or any persistent state. - Origin-locked fetches — The dropdown only fetches credentials for
window.location.href. A malicious page cannot trick the extension into fetching credentials for a different origin. - Closed Shadow DOM — Page JavaScript cannot access injected elements or read credential data.
- textContent only — All user data (names, usernames, URLs) is rendered via
textContent, neverinnerHTML. This prevents XSS from malicious entry names. - Content Security Policy — The extension’s CSP restricts script execution to its own bundled files.

