Memento records meetings, transcribes them and writes documents from them, all on the user's PC. Recordings can be privileged (legal, medical, HR, board meetings), so this document says what Memento protects, against whom, what it promises, what it does not try to defend against, and how to report a problem. The latest audit and its findings are in audits/ (first audit, before 1.0.0: SECURITY-AUDIT-2026-10-07.md; second audit, the 2.0 surface: SECURITY-AUDIT-2026-10-11.md). The audit is repeated before every major version (ROADMAP.md, "Security audit").
| Asset | Where it lives | Why it matters |
|---|---|---|
| Recordings (tracks, mix) | <library>\projects\<id>\tracks\, mix.* |
The most sensitive data; must never leave the PC. Removed by Delete recording and (2.1) by Delete audio and its age setting (Never by default), which deletes only audio files: the files the tracks and mix name inside the folder, the peaks, and audio leftovers in tracks\; never an MP4, the transcript or a document, whatever project.json says. |
| Library folders (2.1) | <library>\folders.json, project.json's folder |
Folder names the user typed (they may name clients or projects). Data only: no directory is created from them, so a name cannot reach the file system; never sent anywhere. |
| Video tracks (2.0) | <library>\projects\<id>\tracks\screen.mp4, camera.mp4 (.part2.mp4, .joined.mp4) |
Everything shown on a captured display (other windows and notifications included) or seen by the camera. Recorded only when the user turns a video source on (Recording mode Audio only by default), never transcribed, analysed or sent anywhere, served to the page only through library.memento like the audio, removed by Delete recording or "Remove video, keep audio" (and Settings' age, Never by default), which also takes any copy a crash left in tracks\ (a part, a join's output or its temporary file) and only ever MP4 files there. Picker thumbnails are made in memory, at most one at a time, and never written. |
| Transcripts, annotations, agendas, attachments | the same project folder | Full text of what was said, names of people. |
| Known voices (2.0, opt-in) | <library>\voices\known.json |
Voice signatures (192 numbers from the voice model per confirmation, at most 10 per name, never audio) under the names the user confirmed, and which recordings confirmed or declined them. A voice signature is biometric data: it can tell whether a later recording contains that person, whoever made it. It is written only while Settings › Speakers › "Remember speakers by voice" is on (off by default) and only when the user names a speaker in Review, never leaves the PC, is not exported, and moves with the library. Turning the setting off stops learning but keeps what was learned; the voices go only when the user deletes them: Forget (one name) or Forget all in Settings (which also removes any copy set aside because the file was damaged, known.json.damaged-…), and Delete recording, which removes that recording's confirmations from the file and from Undo. If known.json cannot be rewritten at that moment (it comes from a newer Memento, or the disk refuses), the recording is still deleted and the confirmations stay until Forget (audit 2, SA2-36). Plain JSON like the transcripts, not encrypted at rest. |
| Speaker embeddings per recording (2.0) | <library>\projects\<id>\voices.json |
One voice-model embedding per speaker group the speakers stage found, whatever the known-voices setting; used to name speakers and, only on the user's request, to learn a known voice. Biometric-adjacent like the above; never exported or sent; deleted with the recording. |
| Clipboard copies (2.0) | Windows clipboard | Transcript and document text the user copies. Marked never to be uploaded to the cloud clipboard; Windows clipboard history (Win+V), if the user turned it on, can keep them. |
| Documents and generation records | <library>\projects\<id>\documents\ |
Summaries, decisions, action items; the record may keep the exact payload sent to an AI provider. |
| AI provider keys | %LOCALAPPDATA%\Memento\secrets.bin (DPAPI, current user) |
Billing and account access at the provider; from 2.5.0 also the optional key of "Your own server". |
| Settings, logs, crash reports | %LOCALAPPDATA%\Memento\ |
Must never contain content or keys. |
| The installed app and its models | %LOCALAPPDATA%\MementoApp\, %LOCALAPPDATA%\Memento\models\ |
Code and model files the app loads and runs. |
- A hostile file the user imports: an agenda (DOCX, XLSX, PDF, image, CSV, Markdown, text), a media file, an attachment, or a whole project folder copied into the library (2.0: with MP4 video tracks and
videoTracks[]entries that recovery, the video stage, Remove video and export read, repair, join or delete; or aknown.jsonin a shared library). It may try to crash or hang the app (zip bombs, decompression bombs, deep nesting, hostile MP4 box sizes, ReDoS), stop recovery for every other recording, escape a folder (path traversal, junctions, reserved names), make a designed deletion take the wrong file, run code (macros, scripts, shortcuts), or reach the network (UNC paths that leak the user's NTLM hash). Since 2.0 another program on the desktop is in the same position: its window can claim any size or title, or hide itself from capture, and the picker lists windows and makes thumbnails of them. - Hostile text aimed at the AI prompts: transcript speech, agenda items, participant names or document edits that try to change the model's instructions, forge citations, smuggle HTML or links into a document, or extract a key.
- A compromised model host or update server: a model file or update package that was replaced, a redirect to another host, a truncated or spliced download.
- Script running inside the interface: if anything ever managed to run script in the WebView2 page, it could call any bridge method. The bridge therefore never trusts the page with file paths, URLs or ids beyond what each method needs. Since 2.0 that includes thumbnails of listed windows and starting a capture during a recording (shown without a Windows border); audit 2, SA2-10, accepts this because nothing has been found that runs script in the page and the page has no network.
- Another local user on the same PC: no access to the user's profile, but possibly write access to a library moved to a shared drive.
- A malicious build dependency: an npm or NuGet package that runs during the build or in CI.
- Nothing leaves the PC without an explicit action. With AI off, Memento makes no network connection except: a model download the user starts in Settings, opening a link the user clicks, the update check (Settings › General › "Install updates automatically", on by default; "Check now" when off), and (2.5.0) requests to "Your own server" when it is at a loopback address, which never leave the PC (a generation with it, or "Test connection"). Verified by the network tests and the OS-level check described in the audits; audit 2 ran it over a whole 2.0 session (video, live transcript, known voices, Tesseract, the local model, exports and copies).
- Audio and video never leave the PC, not even to an AI provider. The payload composer refuses media and has no video input; no video method sends anything anywhere; a test checks that no video file name, source name or MP4 data reaches a request, the preview or a copy.
- Screen and camera are captured only when the user asks (2.0): a display, window or camera is opened only for a recording the user started with it, or for one thumbnail while the Recording screen shows it; listing sources opens nothing. Windows shows its own camera light; the capture border is turned off where Windows allows it because the Recording screen says what is captured. Windows that keep themselves out of captures (protected players, some password managers) are refused rather than recorded black, and Memento's own windows are not offered and are refused by the host too. Camera and screen-capture privacy switches are Windows' own: Memento reads which one is off to say so, never changes them, and only opens the Settings page on request.
- External AI is off by default. When the user turns it on, only the inputs ticked for that document are sent, only to the provider chosen, and the user can preview exactly what will be sent.
- "Your own server" (2.5.0) leaves the PC only where its address does. An OpenAI-compatible server the user runs (Ollama, LM Studio, vLLM, a llama.cpp server). Where it runs is judged from the address text alone, never by a lookup:
localhost, 127.0.0.0/8 and[::1]are this PC, and a server there is treated like the local model (no "Allow external AI services", no send confirmation, nothing held back, the record says it stayed on the PC). Any other address leaves the PC and is treated like a cloud provider: "Allow external AI services" must be on (checked before anything is read or built, and before "Test connection" contacts it), "Ask before every send" holds the job, the share switches limit what it receives, and what the person confirmed is what runs even if Settings changes meanwhile. Plainhttp://is accepted only for this PC and the local network (RFC 1918, link-local, fc00::/7,.localand single-label names); anything else must behttps://, and nothing (no key, no text, no probe) is sent to a plain-http address outside the local network. A name that resolves elsewhere than its text suggests (a hosts-file entry, a split DNS) is judged by its text; a local-network address is only as private as that network. - Keys are encrypted with Windows DPAPI (current-user scope) and are never written to settings, logs, exports, crash reports, project folders or bridge responses (the interface only learns that a key is saved).
- Logs contain no content: no transcript, document or agenda text, no participant names, no keys. Logs contain file paths, ids, counts, codes and timings. File paths can contain a recording's title when the user exports it (the export folder is named after it).
- Downloads are verified: every model file is checked against the SHA-256 in the catalog built into the app before it is used; a partial file is never loaded.
- User data is only deleted through the designed flows (Delete recording, remove attachment, remove model, forget a known voice, the storage options the user chose, "Remove video, keep audio" and its age setting, "Delete audio" and its age setting (2.1), library move after verification; deleting a Library folder deletes no file), never outside the folders they own.
- WebView2 page: served from the app's own files at
https://app.memento/with a strict Content-Security-Policy (default-src 'none', scripts and styles only from the app, no inline script, no remote content of any kind). Navigation, frames, new windows and downloads are refused; host objects, browser permissions, dev tools (in Release), autofill, SmartScreen and crash-dump upload are off. Messages are accepted only from the app's origin, at most 1 MiB and 32 levels deep. Document HTML is rebuilt element by element from an allow-list before it is shown. - Bridge: every method validates its parameters; ids are checked against strict patterns before they become paths; the page cannot name a file on disk (files come from the host's own picker or a drop the host recorded);
app.openExternalopens onlyhttps:links and Windows settings pages. - Project folders are untrusted input: every file name in
project.json(video tracks and their parts included) and inrecording.state.jsonmust stay inside its folder; junctions and symbolic links are never followed when walking, deleting or moving the library. - Parsers run with size, depth, entry-count, pixel and time limits, and turn every failure into a specific, documented error.
- "Your own server" (2.5.0): the same shared HTTP client and request runner as Claude and ChatGPT, so no redirect is followed (a 3xx is a specific error; the bearer key and the transcript never go to another address, SA-36), answers are capped at 4 MiB of text and 8 MiB per stream line or event (SA-45), and an answer that is one JSON document instead of a stream is read with the same cap. The key, optional, is in DPAPI under
serverand is sent only asAuthorization: Bearerwhen one is saved; an address with a user name or password is refused (it would be stored in plain text) and never written to a log or a message. "Test connection" sends onlyGET /v1/models(and Ollama's/api/version), with a 15-second limit and 1 MiB per answer, and only when the person presses it. The server's answers are untrusted like any model's: the same grounding, verification and validator gates apply. - AI: untrusted text is placed in neutralised sections and the prompts say that section content is data, never instructions; every claim must cite a real transcript line, quotes must be the transcript's words, owners must be real participants, and a verifier and a deterministic validator gate everything. Model output is only ever text in the document model; it never reaches a file path, a shell, a URL or raw HTML.
- Native code (whisper.cpp, llama.cpp, sherpa-onnx, and in 2.0 Tesseract with Leptonica) runs in a separate worker process in a Windows job object, so a crash cannot take the recording down; the worker refuses to load DLLs from network shares. Tesseract is never given a file: the app decodes the image with Windows' decoders, within size limits, and hands the worker gray pixels. The live transcript (2.0) uses the same worker; its draft lives in memory only and is never written to the project or the logs. Every model, the Tesseract language data included, is checked against the catalog's SHA-256 before use, and no other model file can be chosen, so the engines' model-parsing vulnerabilities need a tampered app (audit 2, SA2-24/25/26).
- Video files from disk (2.0) are read by a box reader that bounds every size and box count and refuses what no recording has; crash repair only ever cuts an incomplete tail off a fragmented MP4; one unreadable file never stops the recovery of other recordings. These are fuzzed with the agenda harness (audit 2, §5).
- DLL search path: the app loads DLLs by name only from its own folder and System32, never from the current directory or
PATH; Memento's own system calls are pinned to System32. - Tray and Start with Windows (2.0, both off by default) add no network use and no new way in: the tray menu only shows the window, opens the Recording session or quits; the startup entry is the current user's
HKCU\…\Runvalue naming Velopack's launcher in the install folder with--background, written only by an installed copy and removed when turned off and when Memento is uninstalled. Another program running as the same user could already change that key; it gains nothing from Memento's entry. - Supply chain: pinned package versions,
package-lock.json, NuGet restore from nuget.org only, Dependabot, a CycloneDX SBOM and SHA-256 sums attached to every release, release publishing in a separate job with the only write token. - Locked restores and pinned actions (2.4.0, audit 2 SA2-63): every .NET project commits a
packages.lock.jsonand CI restores in locked mode (the publish inbuild/pack.ps1included), so a package graph that differs from the reviewed one fails the build; every GitHub Action inci.ymlandrelease.ymlis pinned to a full commit SHA (the release tag is kept as a comment), and CI installs one exact .NET SDK (8.0.426) instead of the newest8.0.x.
- A compromised Windows installation, an administrator or malware running as the user. Anything running as the user can read the user's files and decrypt DPAPI data; Memento cannot defend against it. DPAPI protects keys from other users and from copies of the file taken off the PC.
- A tampered Memento binary. The model catalog and the update logic are part of the app; if the app itself is replaced, nothing it checks can be trusted.
- Physical access to an unlocked PC.
- The AI provider's own handling of data the user chose to send (see the provider's terms).
- The WebView2 runtime's own background traffic to Microsoft (runtime updates and configuration; see the audit, finding SA-16). It carries no recording, transcript or document data, because the page never loads remote content.
Until code signing is set up (ROADMAP.md, M5), the installer and updates are not Authenticode-signed. Windows SmartScreen will warn on first run, and a user cannot tell a genuine Setup.exe from a modified one by its signature. Updates are only as trustworthy as the project's GitHub releases: Velopack checks each update package against the SHA-256 in the release feed, but the feed comes from the same release. To check a download by hand, compare its SHA-256 with SHA256SUMS.txt on the release page (Get-FileHash MementoApp-win-Setup.exe) and download only from the project's GitHub releases.
Please report security problems privately through GitHub Security Advisories: on the repository, open Security › Advisories › Report a vulnerability. Do not open a public issue for a vulnerability and do not include real recordings or personal data in a report; a synthetic file that reproduces the problem is ideal. There is no security e-mail address.
We aim to acknowledge a report within a week, agree on a fix and a disclosure date with the reporter, and credit the reporter in the release notes unless they prefer otherwise.