MyCRM
Security

A CRM holds every relationship you have.

So this page is specific rather than reassuring. Where the data sits, what protects it, what the product refuses to do, and the claims we are not going to make.

Data ownership and where data lives

Self-hosted

Your server, your database, your disk. We have no access of any kind — no support tunnel, no remote console, no telemetry. If you need us to debug something, you send us what you choose to send us.

Hosted

Your own instance: its own process, its own database, its own encryption key, its own subdomain. It is not a shared table with a customer column — a query that forgot a filter still could not reach another customer's records, because they are in a different database on a different port.

Which country

The region a hosted instance runs in is written into your agreement before you sign it. If data residency matters to you, say so in the first message and we will confirm it in writing rather than in a footnote.

Leaving

Every object exports to CSV from the UI or the API, and a hosted instance can be handed over as its data directory and database. The receiving end is the same binary, so “take your data” means the product keeps working, not that you get a folder of files.

Signing in

There are no passwords anywhere in MyCRM. Not hashed, not salted — absent. A database dump contains no credential to crack, and nobody on your team can reuse the password they used somewhere that got breached.

Magic links

You ask for a link, it arrives by mail, and it exchanges once for a session. Link requests are rate-limited per IP, and the reply is identical whether or not the address belongs to a user — so the endpoint cannot be used to work out who is on your team.

TOTP

An optional second factor per user, from any authenticator app, enabled on your own profile screen. Sessions that owe a TOTP code can do nothing until they present one.

Session cookies

HttpOnly, Secure, SameSite=Lax and host-only — no Domain attribute, so one instance's cookie can never be sent to another instance on a neighbouring subdomain.

Cross-site request forgery

A cookie-authenticated write must also carry an X-Requested-With header. A form posted from someone else's page cannot borrow your session, because a cross-site form cannot set that header.

Roles

Admin, member and read-only. Being honest about the ceiling: there are no field-level permissions and no record-sharing rules yet, so anyone who can read can read everything. If that is a blocker, tell us before you buy.

Scoped API keys

Keys carry read, write or admin scope, are shown once at creation, and are the same credential the UI uses. A key is not a person, so person-scoped shortcuts like @me are rejected for keys rather than silently resolving to somebody.

Connector secrets are sealed

Connecting Stripe or SendGrid means handing MyCRM a credential to hold. Those credentials are encrypted with a master key that lives outside the database — in the data directory or in the environment — and are masked in every API response and on every screen, including for admins.

The practical consequence: a stolen database dump, on its own, does not yield your Stripe key. The equally practical consequence, in the other direction, is that a database restored without its matching master key keeps every record and loses every sealed credential. Back the key up separately, and back it up first.

Where we can, credentials are also scoped down before they arrive. The Stripe connector reads and never writes; it refuses a full secret key at setup rather than accepting one and being trusted not to use it.

The one unauthenticated write path

Hosted lead forms let a stranger create a record in your system of record. That is the point of them, and it is also the largest thing to get right, so it is hardened in one place rather than per-form.

Exact-origin allowlist

Each form names the origins allowed to post to it. Exact matches only — no wildcards, no suffix matching. An origin that is not on the list gets no CORS headers at all, so the request fails closed rather than being half-allowed.

Honeypot and fill token

A decoy field no human sees, plus a signed single-use token that binds the submission to the page render and enforces a minimum fill time. A replayed submission writes nothing.

Durable rate limits

Per-IP and per-form windows recorded in the database, so a restart does not reset a bot's budget, with a cheap in-process gate in front of them and a hard cap on payload size.

No enumeration

The response is byte-identical whether the contact already existed, was created, or was rejected. A form cannot be used to test whether you know someone.

Messages are text

A submitted message is stored as text and rendered as text. It is never treated as HTML, so a payload typed into a public form cannot execute in the browser of the person who reads it.

Never your session

No public handler reads the session cookie, ever. A signed-in admin who visits a malicious page cannot have their identity attached to a submission by accident.

Most CRMs store consent as a boolean and trust everyone downstream to check it. MyCRM stores it three ways on purpose, because the three answer different questions:

  • The contact's consent field is a cache — fast to filter on, never the source of truth.
  • Consent records are the audit trail: purpose, status, source, timestamp and the evidence of the submission that produced them, kept verbatim.
  • The suppression list is keyed by address, not by contact, and handles deliverability. An address can be fully consented and still unsendable, and those are genuinely different states.

One gate checks all three before anything is sent. The most restrictive answer wins, and an error is treated as “no” rather than being logged and stepped over.

What cannot grant consent

Only two things can: a person ticking an explicit, unticked-by-default checkbox, or an administrator affirming it during a CSV import. A connector cannot. A webhook cannot. A form with no consent checkbox on it records unknown, which the gate treats exactly like no. An existing granted is never quietly downgraded by a later blank submission, and an existing denied or revoked is never upgraded by anything.

The no-marketing-before-purchase rule. Some of our own lead captures were made with an explicit promise never to market to that address. That promise is now modelled as data rather than remembered by whoever was in the room — the send gate enforces it. It is a small thing that says most of what we think about consent: the safe behaviour has to be the default one, in code, not the one that requires discipline.

For completeness: there is no marketing send in MyCRM today. The gate is in place ahead of the feature, not behind it.

Backups and recovery

Hosted

We take them, and we restore-test them — a backup nobody has restored is a hypothesis. The database, the data directory and the master key are captured together, because any two of the three without the third is a partial recovery.

Self-hosted

Yours to take, and the same rule applies. Self-hosting spells out what to copy. If you take one thing away from this page: the master key is not in the database, and a restore without it is not a restore.

What we do not do

On this website

  • No third-party trackers. This page loads a cookieless analytics script from our own domain and the shared stylesheet from our own domain. That is the complete list of external requests
  • No ad networks, no session recorders, no tag manager, no social pixels
  • No mail-link contact routes anywhere on this site. The contact form posts into MyCRM itself — we answer you with the product we sell

In the product and the company

  • We do not sell, rent or share your data. There is no advertising business here that would want it
  • Self-hosted instances send us nothing. No licence ping, no usage counter, no crash report
  • Hosted instances are operated by us, so our operators do have server access. We do not go into your data except when you ask us to look at something specific
  • No dark-pattern consent. The default is unknown, and unknown behaves as no
Claims we are not making. There is no SOC 2 report, no ISO certification and no bug-bounty programme. Telling you that is more useful than a page of badges. If you have found something, write to us with “security” in the message and it goes to the top of the queue.
Procurement questions

Send us the questionnaire.

If your side needs answers in a particular format, ask. We would rather write “not yet” in a box than have you discover it after signing.