How MarketOS protects your data
MarketOS is built on two privacy principles: you keep your own keys, and your content stays on your device unless you ask otherwise. Here's exactly what that looks like in practice — what we do, what we never do, and the engineering that backs it.
Trust should be legible. If you can't explain in plain language what a tool does with your data, you can't decide whether you trust it. This post is the explanation.
Nothing below is marketing; every claim here maps to specific code paths in MarketOS, and every one is externally verifiable by inspecting the app, sniffing the network, or reading the open-source repository.
The quick answer
| Question | Answer |
|---|---|
| Do you see my API keys? | No |
| Do you log my prompts? | No |
| Do you log the URLs I audit? | No |
| Do you resell data to anyone? | Never |
| Are my keys encrypted on disk? | Yes (desktop, via OS keychain) |
| Can I audit sites without signing up? | Yes — the wizard runs without a key; only the audit itself requires one |
| Do you have a responsible disclosure policy? | Yes — /.well-known/security.txt |
The rest of this post is the why and how behind each of those answers.
BYOK — bring your own keys, always
MarketOS needs API keys to talk to the AI providers that actually do the work: Gemini, OpenAI, Perplexity, Anthropic, Stability AI, Ideogram, and a handful of others for image generation. The industry default is to collect those keys on your account and proxy every request through the vendor's servers.
We do the opposite. When you paste an API key into MarketOS:
- The key lives on your device only.
- When you generate an image or run a citability test, the MarketOS app calls the provider's API directly from your device with that key.
- The request and response never touch any MarketOS server.
- The provider's bill goes to your account with no markup from us.
The one exception is the Gemini subscriber proxy. If you're on the $19.99/mo subscription tier and haven't added your own Gemini key, MarketOS uses a shared Gemini key on our servers to run your audits. That's the only place a MarketOS server ever sits between you and a provider. Your prompt still isn't logged — we count the request for quota purposes only. If you'd rather eliminate even that proxy, add your own Gemini key in Settings and you're back to pure direct calls.
Lifetime license is strictly BYOK. If you bought the one-time $199 license, you're using your own Gemini key. Our server-side proxy isn't enabled for lifetime users at all. The entire app runs on keys that live only on your machine.
Keys encrypted at rest, on desktop
"Your keys never leave your machine" is a good start, but where exactly are they on your machine? On the desktop app — the one that matters most for sensitive workflows — they're encrypted using your operating system's native keychain.
macOS
Keys encrypted via macOS Keychain using Electron's safeStorage API. The encryption key is tied to your macOS user account and is unlocked automatically when you log in.
Windows
Keys encrypted via Windows DPAPI (Data Protection API). DPAPI ties the encryption to your Windows user account — other users on the same machine can't decrypt your keystore.
Linux
Keys encrypted via libsecret (gnome-keyring or kwallet, depending on your desktop environment). The encrypted blob is stored in your user data directory with mode 0600 (owner-only read/write).
The encrypted blob lives in your app's user data directory as secure-keys.enc. If someone were to take a snapshot of that directory — a backup, a stolen drive image, a malware exfil — the file is useless to them without your OS account password.
The first time you run an updated version of MarketOS after this feature landed, we automatically migrate any keys that were previously stored in plaintext browser localStorage into the encrypted store, then wipe the plaintext copy. No manual step.
On the web version (marketos.org/app), keys live in your browser's localStorage. Browsers don't expose an equivalent OS-keychain API, so that's the best we can do in a pure-web context. We recommend using API keys that are scoped to a specific project or machine so their blast radius is limited if the browser profile gets compromised. The Settings tooltips flag this explicitly for every BYOK provider.
Network-level protections
Even though most of MarketOS runs locally, there are a few server endpoints (for subscribers, for header fetching, for scheduled deliveries). Here's how those are hardened:
SSRF guard
When you audit a URL, some of the checks need to fetch HTTP response headers from that URL. That fetch happens on a MarketOS edge function. Without protection, a malicious request could point us at an internal service ("please audit http://localhost/admin") and get us to act as an HTTP proxy to infrastructure we shouldn't touch.
We block that explicitly. Every URL that reaches the edge function is validated against:
- Loopback addresses (
127.0.0.0/8,::1) - RFC1918 private ranges (
10/8,172.16/12,192.168/16) - Link-local addresses (
169.254/16, including cloud metadata endpoints) - CGNAT (
100.64/10) - Non-HTTP/HTTPS schemes (
file://,javascript:,gopher://) - URLs with embedded credentials (
user:pass@host) - Hostnames ending in
.local,.internal,.intranet - Dangerous port numbers (SSH, MySQL, Redis, MongoDB, etc.)
DNS rebinding defense
A smarter attack doesn't use a private hostname — it uses a public hostname that resolves to a private IP at fetch time. We check against that too: before fetching, we resolve the hostname via Cloudflare's DNS-over-HTTPS and reject the request if any resolved IP falls into any of the private ranges above. Not a perfect defense against TTL-0 rebinds at runtime, but it closes the vast majority of practical cases.
Origin-locked CORS
Our server endpoints reflect only allowlisted origins in their CORS responses — marketos.org, localhost dev ports, and the Electron app. A malicious third-party page can't get your browser to call our API with your bearer token and read the response. Non-browser callers (like the Electron main process and server-to-server tools) still work because CORS doesn't apply to them.
Redacted errors
When an upstream provider returns an error, we echo it to you so you can debug. Before we do, we run the error message through a sanitizer that strips anything matching a Gemini, OpenAI, Anthropic, or Perplexity API key pattern, plus any Bearer token. If an upstream happens to include your key in an error (rare but it's happened), it won't leak through us.
What we never do
- We don't log prompts. Your audit queries, content generation inputs, brand summaries, and chat messages are never persisted on our servers.
- We don't log audit targets. The URLs you audit and the content we extract from them live entirely in your app.
- We don't sell or share data. There's no analytics vendor receiving your interactions, no ad network, no data broker in the picture. The only analytics we have is the privacy-respecting default Netlify gives us for basic site reliability (which doesn't see individual users).
- We don't proxy provider calls for BYOK users. If you supplied your own Gemini key or any non-Gemini key, that call goes straight to the provider. MarketOS is not a hop in the network path.
- We don't ship telemetry without opt-in. No anonymous usage pings leave your desktop app. If we ever add optional diagnostics, it'll be off by default with a clear toggle.
Responsible disclosure
If you find a security issue, email support@driftrail.com. MarketOS is operated by DriftRail, so all disclosures route through that address.
We publish our policy at /.well-known/security.txt per RFC 9116. Highlights:
- We respond within 72 hours.
- We aim to ship fixes for high-severity issues within 7 days.
- We don't retaliate against good-faith research.
- Please don't publicly disclose until we've had a chance to respond.
- In scope: marketos.org, the
/api/v1/*endpoints, the MarketOS desktop app. Out of scope: third-party provider APIs.
The tradeoffs we acknowledge
No tool is a security silver bullet. A few residual risks we won't pretend don't exist:
- Browser localStorage on web. The web app stores keys in localStorage because browsers don't expose an OS-keychain equivalent. If your browser profile is compromised, keys there are readable. Use narrow-scope keys or stick to the desktop app for anything sensitive.
- Anthropic browser-direct access. Anthropic requires a specific header (
anthropic-dangerous-direct-browser-access) to allow the web client to call them directly. That's safer than proxying through us — but it does mean your key is visible in your browser's network tab. Same advice: use a scoped key. - DNS TTL-0 rebinds. Our DNS rebinding defense catches the common case but can't fully defend against an attacker who forces a zero-TTL rebind between our DNS check and our fetch. Netlify Edge doesn't let us pin a resolved IP into
fetch(). This is a rare, noisy attack that would have to be specifically crafted against MarketOS; we still accept the residual risk honestly. - Upstream provider behavior. We have no visibility into what Gemini, OpenAI, Anthropic, or Perplexity do with your prompts once they receive them. Each provider has their own privacy policy; if that matters to you, read theirs.
We'd rather tell you about the rough edges than pretend they don't exist. That's the whole point of legible trust.
The short version
Your keys are yours. Your content is yours. Your audits are yours. MarketOS's job is to make the AI providers do the work you want them to do — directly, on your device, with no middleman inspecting the traffic. We hold the minimum infrastructure needed to make that work and nothing more.
If you ever catch us doing something that doesn't match this post, email us and we'll either fix it or update the post. Trust should be legible.