feat: implement browser extension UI with WebAssembly integration
This commit is contained in:
		| @@ -29,8 +29,67 @@ The browser extension is the main user interface for interacting with the modula | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Script Permissions & Security | ||||
| - **Session Password Handling**: The extension stores the keyspace password (or a derived key) securely in memory only for the duration of an unlocked session. The password is never persisted or written to disk/storage, and is zeroized from memory immediately upon session lock/logout, following cryptographic best practices (see also Developer Notes below). | ||||
| ## Security Considerations | ||||
|  | ||||
| ### Restricting WASM and Session API Access to the Extension | ||||
|  | ||||
| To ensure that sensitive APIs (such as session state, cryptographic operations, and key management) are accessible **only** from the browser extension and not from arbitrary web pages, follow these best practices: | ||||
|  | ||||
| 1. **Export Only Safe, High-Level APIs** | ||||
|    - Use `#[wasm_bindgen]` only on functions you explicitly want to expose to the extension. | ||||
|    - Do **not** export internal helpers, state singletons, or low-level APIs. | ||||
|  | ||||
|    ```rust | ||||
|    // Safe to export | ||||
|    #[wasm_bindgen] | ||||
|    pub fn run_rhai(script: &str) -> Result<JsValue, JsValue> { | ||||
|        // ... | ||||
|    } | ||||
|  | ||||
|    // NOT exported: internal state | ||||
|    // pub static SESSION_MANAGER: ... | ||||
|    ``` | ||||
|  | ||||
| 2. **Do Not Attach WASM Exports to `window` or `globalThis`** | ||||
|    - When loading the WASM module in your extension, do not attach its exports to any global object accessible by web pages. | ||||
|    - Keep all WASM interaction within the extension’s background/content scripts. | ||||
|  | ||||
| 3. **Validate All Inputs** | ||||
|    - Even though only your extension should call WASM APIs, always validate inputs to exported functions to prevent injection or misuse. | ||||
|  | ||||
| 4. **Use Message Passing Carefully** | ||||
|    - If you use `postMessage` or similar mechanisms, always check the message origin and type before processing. | ||||
|    - Only process messages from trusted origins (e.g., your extension’s own scripts). | ||||
|  | ||||
| 5. **Load WASM in Extension-Only Context** | ||||
|    - Load and instantiate the WASM module in a context (such as a background script or content script) that is not accessible to arbitrary websites. | ||||
|    - Never inject your WASM module directly into web page scopes. | ||||
|  | ||||
| #### Example: Secure WASM Export | ||||
|  | ||||
| ```rust | ||||
| // Only export high-level, safe APIs | ||||
| #[wasm_bindgen] | ||||
| pub fn run_rhai(script: &str) -> Result<JsValue, JsValue> { | ||||
|     // ... | ||||
| } | ||||
| // Do NOT export SESSION_MANAGER or internal helpers | ||||
| ``` | ||||
|  | ||||
| #### Example: Secure JS Loading (Extension Only) | ||||
|  | ||||
| ```js | ||||
| // In your extension's background or content script: | ||||
| import init, { run_rhai } from "./your_wasm_module.js"; | ||||
|  | ||||
| // Only your extension's JS can call run_rhai | ||||
| // Do NOT attach run_rhai to window/globalThis | ||||
| ``` | ||||
|  | ||||
| By following these guidelines, your WASM session state and sensitive APIs will only be accessible to your browser extension, not to untrusted web pages. | ||||
|  | ||||
| ### Session Password Handling | ||||
| - The extension stores the keyspace password (or a derived key) securely in memory only for the duration of an unlocked session. The password is never persisted or written to disk/storage, and is zeroized from memory immediately upon session lock/logout, following cryptographic best practices (see also Developer Notes below). | ||||
| - **Signer Access**: Scripts can access the session's signer only after explicit user approval per execution. | ||||
| - **Approval Model**: Every script execution (local or remote) requires user approval. | ||||
| - **No global permissions**: Permissions are not granted globally or permanently. | ||||
|   | ||||
| @@ -54,7 +54,7 @@ async fn main() { | ||||
| use kvstore::{KVStore, WasmStore}; | ||||
|  | ||||
| // Must be called from an async context (e.g., JS Promise) | ||||
| let store = WasmStore::open("mydb").await.unwrap(); | ||||
| let store = WasmStore::open("vault").await.unwrap(); | ||||
| store.set("foo", b"bar").await.unwrap(); | ||||
| let val = store.get("foo").await.unwrap(); | ||||
| // Use the value as needed | ||||
|   | ||||
| @@ -39,7 +39,7 @@ sal/ | ||||
|  | ||||
| - **Each core component (`kvstore`, `vault`, `evm_client`, `rhai`) is a separate crate at the repo root.** | ||||
| - **CLI binary** is in `cli_app` and depends on the core crates. | ||||
| - **WebAssembly target** is in `web_app`. | ||||
| - **WebAssembly target** is in `wasm_app`. | ||||
| - **Rhai bindings** live in their own crate (`rhai/`), so both CLI and WASM can depend on them. | ||||
|  | ||||
| --- | ||||
|   | ||||
		Reference in New Issue
	
	Block a user