01Principles
Three ideas shape everything below.
- A permission is only real if it holds everywhere. A field you hide must stay hidden when it is pulled through a relation, summed into a report, matched by search, or read by AI. A rule that applies only to the grid is not a rule.
- Isolating access should not mean severing data. Products in this category typically isolate by splitting information into separate bases or boards, which breaks every relationship across the split. RowFold isolates access with folders and permissions and leaves the model intact.
- Deleting should be recoverable. Records are soft-deleted so an accident is a visit to Trash rather than a support ticket.
02Signing in
| Control | How it works |
|---|---|
| Password storage | PBKDF2 with HMAC-SHA256, 100,000 iterations, a unique random salt per user, and a 32-byte derived key. Passwords are never stored or logged in a recoverable form. |
| Two-factor authentication | Time-based one-time codes (TOTP, RFC 6238) from any authenticator app, plus single-use recovery codes that are themselves stored hashed. |
| Single sign-on | Google and Microsoft. Only addresses the provider has verified are accepted, so an unverified email cannot open an account. |
| SSO account linking | A signed-in provider account links on the provider's own immutable subject identifier, never on the email address — so a reassigned or spoofed address cannot inherit an existing RowFold account. |
| Secrets at rest | Two-factor seeds and connected-app OAuth tokens are encrypted in the database, not merely stored in it. A dump of the tables does not yield working authenticator secrets or usable third-party tokens. |
| Session cookies | HttpOnly and SameSite-restricted, marked secure, and served over HTTPS with HSTS in production. |
| Brute-force resistance | Two layers. Authentication endpoints are rate-limited per source address, and each account separately counts consecutive failures, locking for 15 minutes after 10. The per-account counter is the one that matters against credential stuffing, where attempts arrive from many addresses at once. |
| Enforced two-factor | The owner of a workspace can require two-factor of everyone in it. People without it are sent to set it up before they can continue, and the requirement applies to members invited later. |
03Sessions & alerts
A sign-in lasts 30 days per device. That is a long time for a stolen cookie to stay useful, so two things bound it.
- Sign out everywhere. One action ends every session on every device, immediately, including the one you are using. Changing a password by reset does the same automatically — otherwise resetting a stolen password would leave the thief's existing session working for the rest of its life, which is the opposite of what someone resetting a password believes they are doing.
- Alerts you can act on. We email you when a sign-in arrives from a device the account has not used before, and when a security setting changes — password, two-factor turned on or off, recovery codes regenerated, or all sessions ended. Turning two-factor off is the first thing an attacker with a live session does, and it is silent otherwise.
Devices are recognised by a long-lived cookie rather than by IP address or browser fingerprint. Those change constantly for ordinary people — a phone moving between wifi and mobile data, a browser updating — and an alert that fires on every commute is one that gets filtered within a fortnight. Clearing your cookies looks like a new device, which is the safe direction to be wrong in.
04Permissions
Access is decided at three levels, each able to override the one above it.
- Workspace role — viewer, contributor, editor, or admin, setting the default for everything inside.
- Table access — per person and per table: full, read and create, read only, or no access at all. "No access" removes the table from view entirely rather than showing a locked door.
- Field access — per person and per field: read-only, or hidden.
Folder-level access grants or removes a whole group of tables in one action, and a folder someone cannot see is absent rather than greyed out — its name does not appear. Because this is an access rule rather than a copy of the data, relationships across the boundary keep working for the people who are allowed to follow them.
05Encryption, hosting & the browser
RowFold runs on Microsoft Azure in the United States. Traffic is encrypted in transit with TLS, HTTP requests are redirected to HTTPS, and production sends HSTS. The database is Azure Database for PostgreSQL with encryption at rest; file storage is Azure Blob Storage, also encrypted at rest.
Requests that change state carry an antiforgery token that is validated server-side, and the application is rate-limited by endpoint class rather than globally, so a burst against one surface cannot exhaust another.
Every response also carries browser-level hardening: X-Content-Type-Options: nosniff so an uploaded file cannot be sniffed into executable script; a referrer policy that stops workspace, table and record ids leaking in the Referer of outbound clicks; a permissions policy denying geolocation, camera, microphone and payment outright, since nothing here asks for them; and a content-security policy setting object-src 'none', base-uri 'self' and form-action 'self'. Signed-in pages refuse to be framed at all; only the surfaces designed to be embedded on your own site — public forms and the chat widget — are framable, and a widget that names its allowed sites is restricted to them.
'unsafe-inline' in it would be decoration — it would pass a scanner while blocking nothing. It is on the list as real work, not as a header we forgot.06Files & attachments
Uploaded files are never written to a publicly served directory. They go to blob storage (or, in local development, to a directory outside the web root), and the only way to read one back is through an endpoint that checks your permission on the owning record first. A file's URL is not a capability: knowing it does not grant access to it.
Attachment metadata is also excluded from every text-based write path in the product — imports, the API, AI edits, and grid pastes cannot construct or alter it. That closes the route by which a crafted value could otherwise be made to point at another account's stored file.
07Public surfaces
Three things answer without a login, each reachable only through an unguessable token rather than by knowing an id: public forms, form file uploads, and inbound email addressed to a workspace mailbox.
Public forms are treated as hostile input by default. Submissions are rate-limited per address, carry a honeypot and an antiforgery token, and — the important part — the server re-validates which fields are eligible and which were conditionally visible. The browser's account of what the form contained is never trusted, so a modified page cannot write to a field the form did not offer. File uploads hand the browser opaque identifiers only; every piece of file metadata is read back server-side at submission, and uploads that are never submitted are swept automatically.
08The API
The public API authenticates with OAuth 2.0 client credentials: a client id and secret are exchanged for a bearer token that expires after an hour. Secrets are shown once at creation and stored hashed, so a leaked database does not yield usable credentials. Requests are rate-limited per credential, and anonymous requests are held to a much lower ceiling than authenticated ones. API access is subject to exactly the same permission resolution as the UI — a token cannot read a field its owner cannot read.
09Deleting & recovering
Deleting a record marks it deleted and moves it to Trash rather than destroying it, so mistakes are reversible by the person who made them. Record changes are captured as events, giving an audit trail of what changed and when. Account deletion and export are covered by the Privacy Policy, including how long content persists in backups.
10What we don't have yet
- No SOC 2 or ISO 27001 report. We have not completed an audit against either framework. If your procurement process requires one, we are not yet a fit.
- No third-party penetration test. The application has been reviewed internally and adversarially, but not by an external firm, and we will publish the summary when that changes.
- No bug bounty programme. We publish a disclosure policy with safe-harbour terms and act on reports (see below), but we do not currently pay for them.
- No script-source restriction in the content-security policy. Described in section 05 — real work rather than a missing header.
- No customer-managed encryption keys, and no choice of data region. Everything runs in the United States.
- No HIPAA, FedRAMP, or similar regime. Do not put regulated health or government data in RowFold.
- No contractual uptime guarantee. We do not offer an SLA today.
11Reporting a vulnerability
If you believe you have found a security issue, email security@rowfold.com with enough detail to reproduce it. We aim to acknowledge within two business days and to tell you what we intend to do about it, and how quickly, within ten. The same address is published in machine-readable form at /.well-known/security.txt (RFC 9116).
Safe harbour. We will not pursue or support legal action against anyone who reports an issue in good faith, provided you give us a reasonable chance to fix it before disclosing publicly, do not access, modify, or retain data belonging to anyone but yourself, and do not degrade the service for others. Testing against your own account and workspaces is explicitly welcome. If you are unsure whether something is in scope, ask first — we would rather answer the question than have you guess.
Please do not use automated scanners against the production service without telling us; the traffic is indistinguishable from an attack and will simply be rate-limited.
12Contact
Security reports and questions: security@rowfold.com. Privacy and data-subject requests: privacy@rowfold.com. Postal: RowFold Inc., 14 Cedar Ave, Suite 200, Portland, OR 97214, USA.
Related: Privacy Policy · Terms of Service