# Attack surface — LexAI > Living inventory of LexAI's exposure. Updated whenever manifest/permissions, storage, or provider handling changes, and before any Chrome Web Store push. Contains **no secrets** — only references. Maintained via the `attack-surface` skill; security review via `security-auditor`. ## Assets | Asset | Type | Tech | Hosted | Auth in | Exposure | Defenses | Review cadence | | --- | --- | --- | --- | --- | --- | --- | --- | | Content script | injected code | WXT/TS | client | n/a | **``, all frames** | `data-lexai` guard; inline styles; max z-index | every manifest/permission change | | Background service worker | LLM proxy | WXT/TS | client | user's provider key | reachable only via extension messages | key never logged; provider-only fetch | every key/provider change | | `chrome.storage.local` | local store | Chrome | client | extension-only | holds `apiKeyEnc`+`encKey` (+ legacy plaintext `apiKey`) | tweetnacl secretbox (see weakness) | every key-handling change | | Provider endpoints | 3rd-party API | HTTPS | OpenAI/Anthropic/Groq/OpenRouter | user's API key | outbound only, user-initiated | HTTPS; key in header only | on provider add/change | | Gitea CI | pipeline | Gitea workflows | self/3p | `GITEATOKEN`, `CWS_*`, `TELEGRAM_*` | build + publish to CWS | secrets in Gitea; **but** `http.sslVerify false` (see gap) | on workflow change | ## Per-asset notes ### Content script — `` - **Exposure:** injects into every frame of every site, including banking, email, internal apps. Biggest privacy surface and the #1 Chrome Web Store review slowdown. - **Mitigation (proposed):** narrow to `activeTab` + on-demand injection, or a user allowlist (TASKS #1 / D-PROPOSED). Decide before a serious CWS push. ### API-key storage — obfuscation, not protection - **Exposure:** `encKey` is stored in `chrome.storage.local` next to `apiKeyEnc`; anyone who can read storage can decrypt. The "encrypted" claim over-promises. - **Secrets location:** `chrome.storage.local` (user's own browser). Never in repo, never logged. - **Mitigation (proposed):** derive the key from `chrome.storage.session` / WebCrypto / a passphrase, and describe it honestly in the UI (TASKS #2 / D-...-06). ### Debug logging leak - **Exposure:** `content.ts` logs selection text and element values to the host-page console — readable by the page. - **Mitigation:** gate behind `import.meta.env.DEV` (TASKS #3). ### CI TLS verification disabled - **Exposure:** both Gitea workflows set `http.sslVerify false` and `git clone` into `/tmp`. - **Mitigation:** use the checked-out workspace and restore TLS verification (TASKS #17). ## Model / harness input surface (prompt-injection) The extension sends **user-selected page text** to the chosen LLM with a fixed system prompt. Page-controlled text is untrusted input to the provider call. | Input avenue | Consuming model | Reachable actions | Exposure | Defense in place | | --- | --- | --- | --- | --- | | Selected page text → `ANALYZE_TEXT` | user's provider | returns text shown in modal; user chooses Replace/Copy | injected instructions in page text could steer the model's output | user reviews output before Replace; no tool-calling; output is inert text | - **Note:** exposure is low because the model output is inert (no tool execution) and the user gates Replace. Run `prompt-injection-audit` if LexAI ever adds auto-apply, tool use, or agentic actions. ## Gaps / unknowns - Host-permission narrowing not yet decided (TASKS #1). - Key-derivation redesign not yet done (TASKS #2). - No automated check that production builds exclude debug logs (TASKS #3).