DSK-11Recommended
Check the sender and content of every message to the main process
Each handler in the main process checks which window and page sent the message and validates every argument against a schema. A path or command never comes from the page as is.
How to do it
Treat the window as you treat a browser talking to a server. The main process holds the power, and the window can be fooled by injected script. Check event.senderFrame.url against your own app address. Validate types and lengths as accept only the fields you expect does. Take an ID and look up the path yourself. When a handler starts a program, follow never pass input to a shell.
Examples
JavaScript example
const APP_ORIGIN = 'app://ledgerly';
const InvoiceId = z.string().regex(/^inv_[a-z0-9]{12}$/);
ipcMain.handle('invoice:open', (event, rawId) => {
if (new URL(event.senderFrame.url).origin !== APP_ORIGIN) throw new Error('unknown sender');
const id = InvoiceId.parse(rawId);
return invoices.open(path.join(invoiceDir, `${id}.pdf`));
});
Plain text example
#[tauri::command]
fn open_invoice(id: String, dir: tauri::State<InvoiceDir>) -> Result<Vec<u8>, String> {
let valid = id.len() == 16 && id.starts_with("inv_") && id[4..].chars().all(|c| c.is_ascii_alphanumeric());
if !valid {
return Err("bad invoice id".into());
}
std::fs::read(dir.0.join(format!("{id}.pdf"))).map_err(|_| "not found".into())
}
How to check
A test calls each handler with a sender frame from another address. It refuses. A test sends ../../.ssh/id_rsa as an invoice ID. The handler refuses it and opens no file.
Sources
Related rules
- SEC-25 Accept only the fields you expect in Adversarial testing
- SEC-11 Never pass input to a shell in Adversarial testing
- DSK-12 Open outside links only after checking the address in Desktop apps, extensions and CLIs
- DSK-16 Treat messages from web pages and content scripts as untrusted in Desktop apps, extensions and CLIs
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/desktop-apps/web-code-inside-desktop-apps/validate-ipc">Agent Wranglers desktop apps, extensions and CLIs playbook</a>. In code you write, add a comment next to it with the same link.