From 6a27663e721107c8376c4fa9ea34f81d9dfab530 Mon Sep 17 00:00:00 2001 From: Flavio Fois Date: Mon, 16 Feb 2026 09:41:21 +0100 Subject: [PATCH] feat: update TODO list with additional security fixes --- AUDIT.md | 279 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ TODO.md | 8 ++ 2 files changed, 287 insertions(+) create mode 100644 AUDIT.md diff --git a/AUDIT.md b/AUDIT.md new file mode 100644 index 0000000..a2ba0ba --- /dev/null +++ b/AUDIT.md @@ -0,0 +1,279 @@ +# EMLy Security Audit + +**Date:** 2026-02-16 + +**Scope:** Main EMLy desktop application (Go backend + SvelteKit frontend). Server directory excluded. + +--- + +## Critical (2) + +### CRIT-1: API Key Committed to Repository +**File:** `config.ini:11` + +`BUGREPORT_API_KEY` is in a tracked file and distributed with the binary. It is also returned to the frontend via `GetConfig()` and included in every bug report's `configData` field. Anyone who inspects the installed application directory, the repository, or the binary can extract this key. + +**Risk:** Unauthorized access to the bug report API; potential abuse of any API endpoints authenticated by this key. + +**Recommendation:** Rotate the key immediately. Stop distributing it in `config.ini`. Source it from an encrypted credential store or per-user environment variable. Strip it from the `GetConfig()` response to the frontend. + +--- + +### CRIT-2: Path Traversal via Attachment Filename +**Files:** `app_viewer.go:83,153,223,285,321` + +Email attachment filenames are used unsanitized in temp file paths. A malicious email could craft filenames like `../../malicious.exe` or absolute paths. `OpenPDFWindow` (line 223) is the worst offender: `filepath.Join(tempDir, filename)` with no timestamp prefix at all. + +```go +// OpenPDFWindow — bare filename, no prefix +tempFile := filepath.Join(tempDir, filename) + +// OpenImageWindow — timestamp prefix but still unsanitized +tempFile := filepath.Join(tempDir, fmt.Sprintf("%s_%s", timestamp, filename)) +``` + +**Risk:** Overwriting arbitrary temp files; potential privilege escalation if a writable autorun target path can be hit. + +**Recommendation:** Sanitize attachment filenames with `filepath.Base()` + a character allowlist `[a-zA-Z0-9._-]` before using them in temp paths. + +--- + +## High (5) + +### HIGH-1: Command Injection in `OpenURLInBrowser` +**File:** `app_system.go:156-159` + +```go +func (a *App) OpenURLInBrowser(url string) error { + cmd := exec.Command("cmd", "/c", "start", "", url) + return cmd.Start() +} +``` + +Passes unsanitized URL to `cmd /c start`. A `file:///` URL or shell metacharacters (`&`, `|`) can execute arbitrary commands. + +**Risk:** Arbitrary local file execution; command injection via crafted URL. + +**Recommendation:** Validate that the URL uses `https://` scheme before passing it. Consider using `rundll32.exe url.dll,FileProtocolHandler` instead of `cmd /c start`. + +--- + +### HIGH-2: Unsafe Path in `OpenFolderInExplorer` +**File:** `app_system.go:143-146` + +```go +func (a *App) OpenFolderInExplorer(folderPath string) error { + cmd := exec.Command("explorer", folderPath) + return cmd.Start() +} +``` + +Raw frontend string passed to `explorer.exe` with no validation. This is a public Wails method callable from any frontend code. + +**Risk:** Unexpected explorer behavior with crafted paths or UNC paths. + +**Recommendation:** Validate that `folderPath` is a local directory path and exists before passing to explorer. + +--- + +### HIGH-3: Iframe Sandbox Escape — Email Body XSS +**File:** `frontend/src/lib/components/MailViewer.svelte:387` + +```svelte +