Some checks failed
CI — Test & Build / Test & Build (push) Failing after 39s
- Added a new "Prompt Builder" tab in the Popup for generating AI prompts with customizable parameters. - Introduced new state variables for managing prompt styles, personas, formats, and models. - Enhanced the Options page to fetch and display models based on the provided API key. - Updated the actions and types to include the new 'prompt' action and its associated parameters. - Implemented migration logic for legacy plaintext API keys to encrypted storage. - Updated the getSystemPrompt function to incorporate prompt parameters for better instruction generation. - Added tests for the new functionality, including context menu entries and prompt generation logic.
3.6 KiB
3.6 KiB
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-surfaceskill; security review viasecurity-auditor.
Assets
| Asset | Type | Tech | Hosted | Auth in | Exposure | Defenses | Review cadence |
|---|---|---|---|---|---|---|---|
| Content script | injected code | WXT/TS | client | n/a | <all_urls>, 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 — <all_urls>
- 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:
encKeyis stored inchrome.storage.localnext toapiKeyEnc; 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.tslogs 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 falseandgit cloneinto/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-auditif 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).