// Security
Security & data protection.
How we protect your account, your keys, and your data — in plain terms first, then in full technical detail.
Reviewing us for your IT team or filling in a vendor questionnaire? Skip straight to the technical version: key hierarchy, isolation, sub-processors, and outbound request safety.
The short version
Your data is scrambled before it's stored
Contact details, phone numbers, addresses, your notes and captured replies are encrypted before they're written down — using a key that belongs to your workspace and no one else's. Someone who walked off with our database would get unreadable noise.
And on the way there
Everything between your browser and us travels over an encrypted connection. Nothing moves in the clear.
Your key isn't kept next to your data
The key that unlocks your workspace is held by Amazon's managed key service, not stored alongside the data it opens. Every use of it is recorded, and it can be switched off in seconds.
One workspace can't see another
Your leads, settings, keys and inbox are yours. Other customers can't reach them — and even a bug that got past the first check would hit data locked with a key that isn't theirs.
We don't store your password
We keep a one-way scramble of it, not the password itself. We can't tell you what yours is, because we genuinely don't know it.
Or skip the password entirely
Sign in with Google, GitHub, or Microsoft and your account lives with the identity provider you already trust — one less password to manage.
Your connected accounts stay yours
AI keys, mailbox connections, CRM and phone logins are encrypted, used only to run your own jobs, never exposed to prospects, and disconnectable at any time.
We ask for the least mailbox access that works
With Gmail or SendGrid we take permission to send mail, not to read yours, and replies find their way back by a separate route. Microsoft 365 is the exception: Graph reads the mailbox directly to catch replies and bounces, so connecting one grants send and read in a single consent. Revoke either at any time from the provider.
We never see your card
Card details go straight to Stripe. We hold a customer reference and your subscription status — nothing you could pay with.
Spending can't run away
Your prepaid balance is the built-in stop — when it runs out, AI pauses. On our keys you can set a hard monthly cap per workspace as well; it's off until you set one. With your own keys those calls bill your provider directly, so set your ceiling there too.
We name everyone else who touches your data
Every third party is listed in our Privacy Notice, a Data Processing Agreement is available if you need one, and we don't sell data.
Delete your workspace and it's really gone
Deleting a workspace destroys its key, which makes everything that workspace ever encrypted unreadable in the live database. Backups are whole-database snapshots, so they age out on their own schedule rather than being rewritten.
The one thing we won't pretend
Your automated emails go out while you're asleep, Proto scores prospects with nobody watching, and your prospects' brief pages get served to people who aren't logged in. All of that only works if the software can unscramble your data on its own — which means we could too, if we chose to.
So the honest description is encrypted at rest, per workspace; our access is restricted, recorded, and revocable — not "we can't read your data." Any vendor running unattended automation on your behalf who tells you otherwise is worth a second question. The technical version below spells out exactly what that buys you and what it doesn't.
The technical version
Everything above, with the detail a security reviewer will ask for — written for whoever has to sign the vendor off. If something you need isn't here, ask us and we'll answer directly.
Encryption at rest
Three separate layers
Everything moves over HTTPS/TLS. At rest, three different kinds of data are protected separately, and no key is ever used for two purposes.
Connected credentials — the API keys and OAuth tokens you connect (AI keys, Google Maps, CRM and telephony credentials, mailbox tokens) are encrypted with AES-256-GCM before they are written.
Your prospect data — contact email addresses and phone numbers, business addresses, rep notes, decision-maker contacts, captured reply text and the prospect scoring queue are encrypted at rest under a data key unique to your workspace. Your workspace's key is itself stored wrapped by a key-encryption key held in AWS KMS, so the ciphertext and the key that opens it never sit in the same place — and the key that opens it never sits in our environment at all.
Everything else — operational data that isn't personal (scores, timestamps, counters, settings) is stored in the clear, so the product can query it without holding keys open. Two exceptions are worth naming rather than filing under "operational": the recipient address, subject and full body of every email we send on your behalf are kept in the clear as your per-lead send history, and a generated demo page carries the lead's own phone, email and address by design — it is a web page we are about to show that business.
The key hierarchy
| Key | What it does | Where it lives |
|---|---|---|
| Key-encryption key | Wraps every workspace's data key. Never touches a data value. | AWS KMS. The key material never leaves the service — we call it to wrap and unwrap, and never hold it. |
| Workspace data key | One per workspace, 256-bit, generated at random. Stored only in wrapped form. | Database, encrypted. |
| Field key | AES-256-GCM on individual column values. Derived from the data key via HKDF. | Derived in memory, never stored. |
| Index key | HMAC-SHA256 for blind indexes (below). Derived separately so it can never decrypt anything. | Derived in memory, never stored. |
Each encrypted value is bound to your workspace id as additional authenticated data. A row lifted out of one workspace and dropped into another does not decrypt — it fails closed rather than leaking across.
Key access is logged and revocable
Because the wrapping key lives in a managed key service rather than in a configuration variable, every unwrap is an authenticated API call that leaves an audit record, and access can be withdrawn in seconds — which makes every workspace key unopenable immediately, without re-encrypting a single row, since the data keys themselves never change.
To be precise about the limit: this doesn't stop our own running application from decrypting, because it has to. What it changes is that the capability is online, recorded, and revocable — rather than a secret that, once copied, works forever and silently.
Blind indexes, so we don't need plaintext to match
AES-GCM is randomised: the same email address encrypts to a different value every time, which means the database cannot compare two addresses. That matters most for the thing you'd least want broken — the opt-out list. If a suppressed address couldn't be matched, someone who unsubscribed could be emailed again.
So alongside each encrypted address we store a keyed HMAC-SHA256 of its normalised form — a blind index. Equality checks (is this address suppressed? has this lead already been imported?) run against the index while the address itself stays encrypted. The index key is derived separately from the field key, so it can confirm that two values match without being able to reveal either one.
What that protects — and what it doesn't
The threat it's built for
Workspace encryption is aimed squarely at a database compromise: a leaked connection string, a database dump restored on someone's laptop, a read replica, a console session, a stolen backup. None of those alone yields a readable prospect book, because the key isn't in the database.
What we will not claim
It does not make us blind to your data, and we won't market it as if it did. Your automated senders fire while you're asleep, the scoring worker runs unattended, and your prospects' brief pages are served to people who aren't logged in. All of that needs plaintext with no human present, so the running application must be able to decrypt — and therefore so can whoever operates it.
The honest description is: encrypted at rest per workspace; operator access is possible, restricted, and auditable. Not "we can't read your data." Any vendor running unattended automation on your behalf who tells you otherwise is worth a second question.
Deletion is cryptographic
Deleting a workspace destroys its data key, so every value that workspace
ever encrypted becomes permanently unreadable in the live
database — an erasure guarantee a DELETE statement
cannot give you, because it holds even against a row someone forgot to
delete.
Be clear about the limit: our backups are whole-database snapshots, and a snapshot taken before the deletion contains that workspace's wrapped key beside its ciphertext. Those age out on their own schedule rather than being rewritten — point-in-time recovery on our database provider runs to seven days, and the off-platform encrypted dumps are retained about three months. We don't exclude the key table from the dump, because a backup that cannot be restored is not a backup.
Isolation & access
Row-level workspace scoping
Every table carrying customer data is scoped by workspace id, and queries are issued through repositories that apply that scope rather than leaving it to each caller to remember.
Isolation enforced twice
Scoping is the first line; per-workspace keys are the second. Even a query that escaped its scope returns values encrypted under a key bound to a different workspace, which won't open.
Password storage
Salted, memory-hard scrypt hashes with constant-time verification. Plaintext passwords are never stored and never logged.
Single sign-on
Sign in with Google, GitHub, or Microsoft instead of a password, so account lifecycle stays with your identity provider. SSO signups are password-less by design.
Roles and per-seat controls
Admin and member roles gate the back office, with platform-only controls separated from workspace admin controls. Individual AI capabilities can be toggled per seat.
Separate billing boundaries
If you invoice your own clients through the platform, that runs on your Stripe account and your webhook secret — deliberately sharing nothing with our billing, so your revenue never lands in our ledger.
Your mailboxes and connected accounts
We ask for the narrowest scope that does the job
Sending email needs a send scope. Reading replies out of a Gmail mailbox needs a restricted read scope — a much broader permission, and one that would let us read mail unrelated to your outreach. We didn't want that permission, so for Gmail and SendGrid we don't take it.
Instead, reply capture is optional and works without mailbox access: your
outreach carries a per-lead tokenised Reply-To address, the
prospect's reply arrives at that address, and it's matched back to the
lead and forwarded into your real inbox. We see replies to our own outreach
and nothing else in your mailbox.
Microsoft 365 works the other way, and it is the one place we do hold read
access. Graph has no send-only path to reply and bounce capture, so
connecting a Microsoft mailbox grants Mail.Send and
Mail.Read in a single consent — for the workspace mailbox and
for each seat inbox — and we read it directly. If that is more than you
want to grant, send through Gmail or SendGrid and use the tokenised
reply route above. Either grant is revocable from your Microsoft account
at any time.
Token handling
OAuth refresh tokens are encrypted at rest. Microsoft rotates refresh tokens on use, so each run refreshes once and persists the replacement. A daily health check exercises every connected Gmail token — workspace and per-seat — and alerts you when a grant has expired or been revoked, so a dead connection surfaces as a warning rather than as silently unsent email. Microsoft connections are deliberately not probed on a schedule, because exercising one rotates its token; a dead Microsoft grant surfaces through the inbox poller instead.
You can disconnect any mailbox, CRM, telephony or AI credential from Settings at any time; revoking the grant at the provider works too, and the health check will tell you it happened.
Outbound request safety
The product fetches prospect websites to score them and build demos, and those URLs come from map results, CSV imports and hand-edited leads — in other words, attacker-influenceable input pointed at our own network position. This is the classic server-side request forgery setup, so every such fetch goes through one guarded path that does three things a URL allowlist doesn't:
- Rejects non-public addresses after resolution — IPv4 and IPv6, including the IPv4-mapped and NAT64 spellings that bypass naive checks.
- Re-validates every redirect hop. A public host answering
302 → http://127.0.0.1/is the standard way around a first-hop-only check. - Pins the socket to the address it validated, so a DNS answer that changes between the check and the connection has no second resolution to poison.
Fetched page content is treated as untrusted input to the generation step, never as instructions.
AI processing
Prospect scoring, demo building and email drafting call Anthropic's API. What's sent is the prospect's own public website content plus the lead fields the task needs — not your whole database, and not your other workspaces. Anthropic is named as a sub-processor in our Privacy Notice and covered by our DPA.
On Scale and Agency you can bring your own AI key, in which case those calls run under your own provider account and your own terms, and we never hold the key in plaintext. Either way, a hard per-workspace monthly budget cap pauses AI before spend can run away, and per-seat toggles control which team members can use which AI helpers.
Platform & supply chain
Three runtime dependencies
The application ships with three third-party runtime packages: the PostgreSQL driver, the Anthropic SDK, and Chromium for the scoring worker. The AWS request signer, the Stripe client, the email provider clients and all cryptography are written directly against documented APIs and Node's own crypto library rather than pulled in as packages.
That is a deliberate trade — more of our own code to maintain, in exchange for a supply-chain surface small enough to read. Anything running inside the application can read its environment, so every dependency added is another party who could reach the keys. We'd rather write the signer.
Hosting and sub-processors
The application runs as serverless functions on Netlify with a managed PostgreSQL database. Every third party that touches your data — hosting, database, AI, email delivery, payments, and any CRM or telephony provider you choose to connect — is named in our Privacy Notice. We don't sell data, and a Data Processing Agreement is available for customers who need one.
Webhooks and inbound requests
Payments (HMAC) and telephony status callbacks (HMAC or Ed25519, depending on provider) are signature-verified before they are acted on. Payment events are idempotent and deduplicated, and a write we couldn't record returns an error so the sender retries rather than us acknowledging a payment we didn't store.
Inbound mail is the exception, because the provider doesn't sign it. That route is authenticated on a shared secret in the endpoint URL plus an unguessable per-lead token that has to match a real lead in your workspace, and a message whose sender fails SPF or DKIM is dropped rather than classified.
Data lifecycle
Export
Your lead pipeline exports to CSV from Reports in the back office. Email support@stellarreach.app if you need a full-account extract in a particular format.
Deletion
Deleting your workspace destroys its data key, which makes its encrypted data unreadable everywhere it exists, backups included. Retention specifics are in the Privacy Notice.
Your prospects' rights
Opt-outs are enforced by a suppression list matched on blind index, so a person who unsubscribes stays suppressed even though their address is stored encrypted.
Payment data
Card details go to Stripe and are never seen or stored by us. We hold a customer reference and subscription state, nothing more.
Responsible disclosure
We welcome reports from security researchers. If you believe you've found a vulnerability in StellarReach, email support@stellarreach.app with the details and steps to reproduce. We'll acknowledge your report, keep you updated, and work to resolve confirmed issues promptly.
Please act in good faith: give us a reasonable chance to fix the issue before any public disclosure, avoid accessing or modifying data that isn't yours, and don't run tests that could degrade the service for others (for example, denial-of-service or large-scale automated scanning).
Shared responsibility
Security is a partnership. We protect the platform; you help by using a strong, unique password, keeping your connected accounts and API keys secure, limiting who can access your workspace, and making sure your outreach complies with applicable law. See our Terms of Service and Privacy Notice for the full picture.
Questions about security?
Send us your security questionnaire, or ask a specific question — a person will answer it.
Contact us