Security
How RFP.co handles customer data: tenant isolation, encryption, access control, retention, subprocessors and how to report a vulnerability.
Solicitation documents and draft proposals are commercially sensitive: they carry your pricing, your staffing and your judgement about a competitor. This page describes what RFP.co actually does with them — and, below, what it does not do yet.
Everything here is a mechanism in the running software rather than an aspiration. The binding version of anything contractual is in the terms, the privacy policy and the Data Processing Addendum.
How the platform is built
Tenant isolation is structural, not a convention
Isolation is enforced at the query layer rather than left to each route to remember. A scoped database client cannot express an unscoped query, so a developer who forgets a filter gets no rows instead of another customer’s rows. Every model in the schema is explicitly classified by tenancy mode, and the test suite fails if a new one is added without a classification.
Passwords are hashed with Argon2id
Argon2id, memory-hard and tuned so that GPU parallelism buys an attacker much less than it would against bcrypt or PBKDF2. Stored hashes carry their own parameters, so the cost can be raised later and existing credentials are rehashed on next sign-in rather than left at the old setting.
Session tokens are never stored
What the database holds is an HMAC-SHA256 fingerprint of each session, verification link, password reset and invitation — keyed by a server-side secret. A copy of the database, on its own, yields nothing that can be replayed as a session. Rotating that secret invalidates every outstanding token at once, which is what rotating a secret ought to mean.
Federated sign-in uses PKCE
Google sign-in is an authorization code flow with PKCE, the verifier held server-side and only its SHA-256 challenge sent to the provider. An intercepted authorization code is not sufficient to complete an exchange.
Authentication is rate limited
Sign-in, registration and password reset are rate limited against a shared store rather than per process, so limits hold across replicas rather than multiplying by the number of them.
Submission records cannot be rewritten
What you submitted, and when, is immutable — enforced by database triggers, not by application code that a future change could route around. A produced export may expire, but the record of it is append-only. A requirement that turns out not to apply is marked as such; nothing in the compliance history is deleted.
Documents are private by default
Uploaded solicitations and generated proposals live in object storage with no public access path. Every download is authorized per request against the requesting workspace. Share links carry their own tokens, may be password protected, and revocation is re-read on each request rather than cached.
Data is processed in the European Union
The platform runs in Falkenstein, Germany, and document storage is pinned to an EU jurisdiction at the storage layer — a contractual guarantee from the provider rather than a best-effort region preference. Traffic is served over TLS, and objects are encrypted at rest by the storage provider.
Reporting a vulnerability
Write to security@rfp.co. Include what you did, what happened and what you expected. Research conducted in good faith — without exfiltrating data belonging to other customers, degrading the service, or accessing an account that is not yours — is welcome, and we will not pursue legal action over it.
There is no paid bounty programme. We will acknowledge your report, tell you what we found, and credit you when a fix ships if you would like to be named.
Who else sees your data
Every third party that processes customer data is named in the subprocessor list, along with what it receives and where it processes. We give 30 days’ notice before adding one, and a customer who objects on reasonable data protection grounds may terminate the affected service for a refund.
See what you are not bidding on.
Connect a source, describe what your company does, and look at the opportunities that come back before deciding whether any of this is worth your time.