One workspace can never
see another's leads
OSSCRM holds sales pipelines, email credentials and AI keys for many companies at once. What follows is what the code does today, not a list of intentions — each item names the mechanism, because a security page without mechanisms is a promise.
How leads are kept apart
Isolation is not one check that could be forgotten. It is enforced at four levels, and a row would have to slip past all four to reach the wrong company.
Four independent checks. A row would have to slip past all of them.
Every row carries its owner
Leads, campaigns, templates, suppressions, invoices and credentials all store a tenant id. There is no shared table where records from two companies sit side by side without one.
Every query is scoped, not filtered afterwards
Reads go through a single tenant filter built from the caller's token — the workspace id is taken from the signed JWT, never from a URL, a body or a header the browser can set.
The database enforces it too
The lead de-duplication index is unique on (tenant, key), not on the key alone. Two companies scraping the same business get their own row each; neither can collide with, overwrite or discover the other's.
Roles narrow it further, inside a workspace
Super admin, manager and associate see different data. An associate sees only leads assigned to them, and the check runs on the server — hiding a button is not access control.
What an attacker tries, and what stops it
Named attacks rather than named virtues — your reviewer is going to ask in these terms anyway. Filter by the surface they would come at.
Scope comes from the signed JWT, never from a URL, a body or a header. There is no request shape that names a different workspace.
22 random URL-safe characters, and an unknown token is answered exactly like a valid one — so the space cannot be probed.
Contact and reply text is stored as data. It is never rendered into an email, never interpolated into a query, never used to build a template.
reCAPTCHA v3 on sign-in and sign-up, scored server-side, plus per-IP rate limits on every unauthenticated write.
Provider keys, Twilio tokens and AI keys are AES-256 encrypted before they are written. No endpoint returns one — the UI shows a fingerprint.
The action is signed into the token and checked on the server, so one minted on sign-up cannot be spent on sign-in.
Every unauthenticated write is length-capped and rate-limited per IP, counted at the edge before it reaches the database.
A billable event is unique on (workspace, lead, campaign, kind) in the database, so a race or a retry cannot double-count.
The suppression list is checked when the email is written AND again immediately before it is sent. The later check is the one that decides.
The de-duplication index is unique on (workspace, key), not on the key alone. Two customers scraping the same business get a row each.
Your mail account is yours
The single fastest way to lose a sending domain is to share it. So OSSCRM never sends campaign mail on its own reputation, and never mixes one customer's traffic with another's.
Registered on the provider's portal in your name, on a domain you verified. We hold an encrypted copy and nothing else.
Your mail never queues behind another company's, and another company's complaints can never affect your deliverability.
Transactional (OTP, invoices, reports) and promotional (campaigns) are separate accounts. A campaign cannot touch the transactional one — that is what gets an account suspended.
The allowance on your screen is fetched from your provider account. It is enforced per workspace and spans every campaign, so two campaigns cannot each spend the whole day.
Nothing is sent until every gate opens
A scheduled departure is not a promise to send. It is a request that has to clear six checks, and any one of them refuses rather than guesses.
- 🔒Automation is not haltedA billing or auth refusal from your AI provider latches the workspace. The schedule is skipped, not consumed.
- 🔒A promotional provider existsCampaign mail will not fall back to your transactional account. It refuses and names what is missing.
- 🔒The unsubscribe link is reachableIf the public base URL is not a public https address, every email would carry a dead opt-out. Refused.
- 🔒The daily cap has roomCounted per workspace across every campaign, from what actually went out — not from what was planned.
- 🔒The address is not suppressedChecked again here, after it was already checked at write time. An opt-out that arrived in between still wins.
- 🔒A human approved the copyAssigning leads sends nothing. Departing is a separate, deliberate act, and the words were read first.
- 📨Only then does it sendAny one refusal stops the chain — it never guesses.
Credentials and keys
Encrypted at rest, never returned
Email provider keys, Twilio tokens and AI keys are AES-256 encrypted with a server-side key before they touch the database, and no endpoint returns one. The interface shows a fingerprint — enough to tell two keys apart, useless to anyone who steals it.
Your AI key, your account
Each workspace brings its own Anthropic, OpenAI or Gemini key. Your prompts — your leads, your pitch, your objection handling — travel on your account, not on a key shared with every other customer, and the usage is billed to whoever spent it.
Your sending account, your reputation
Campaign mail goes through a provider you registered yourself, on a domain you verified. Your mail never queues behind another company's and another company's complaints can never affect your deliverability.
Decrypted only at the moment of use
A key is decrypted when a call is placed or an email is sent, and not held in a cache that outlives the request.
The public surface
Single-purpose tokens
The landing page and unsubscribe link a prospect receives carry a 22-character random token that grants exactly two things: read this product's public copy, and record that this recipient is interested. It cannot read a lead, a campaign or anything else.
Unknown tokens answer like real ones
A token that does not resolve is answered identically to one that does, so the token space cannot be probed to discover which recipients exist.
Public writes are capped and rate-limited
The contact form and reply box are unauthenticated by necessity — the sender has no account. Every field is length-capped, every write is rate-limited per IP, and the text is stored as data: never rendered into an email, never interpolated into a query.
No location is ever requested
There is no geolocation prompt anywhere on this site. The contact map draws anonymous dots rounded to about 11 km, with no IP and no identifier, deleted after 30 days by the database itself.
Sending, and stopping
Sending is gated, and refuses rather than guesses
Campaign email cannot leave without a promotional provider configured, a publicly reachable unsubscribe URL and an explicit server-side switch. A misconfiguration refuses instead of sending mail nobody can opt out of.
Opt-out is permanent and checked first
A suppressed address is unique per workspace and is checked before the next email is even written. An unsubscribe or a spam complaint cannot be deleted from the list by anyone.
Follow-ups have a hard cap
Three, then the lead is dropped with a written reason and no automation touches it again. The cap is enforced in the pipeline, not left to a person to remember.
Billing events cannot double-count
A billable click is unique on (workspace, lead, campaign, kind) in the database, so a race or a retry cannot charge twice for one prospect.
Your side of the line
Written for the DPDP Act, 2023
Data Principal and Data Fiduciary roles are kept apart: for your account data we are the Fiduciary; for the leads inside your workspace, you are, and we process them only to run the features you use.
A private deployment, if you need one
Regulated buyers can have OSSCRM run in their own cloud account, so customer data never leaves infrastructure they control. Available on the enterprise plan.
Ask us to prove any of it
Every claim on this page names the mechanism behind it, so it can be checked rather than believed. We will walk your engineers through any of them before you buy.
Found something wrong? Write to our security address — we would rather hear it from you.
Bring it to your security reviewer
Every claim on this page names the mechanism behind it. Ask us about any of them.