Security & Trust · Controls Inventory

Built fail-closed, isolated, and auditable.

This is a controls inventory, written for the people who review security for a living. Each section states what's actually in place, in specifics. We move payment instructions, never funds. We hold no money, run no settlement account, and are not a bank. We assessed ourselves against every Level 2 and Level 3 requirement of OWASP ASVS v5, and against the ISO 27001 and SOC 2 control sets as a checklist. This is a code-verified internal assessment, not a certification claim.

§ 0

Posture at a glance

  • No custody. We move the instruction, your customer's bank moves the money.
  • Fail-closed by default at every boundary. When something is ambiguous or unreachable, the system stops.
  • Isolated at the database, not just the application. No tenant scope set means zero rows.
  • Authenticated cryptography throughout. No unauthenticated modes in production.
  • Not a bank, not a PSD2 AISP or PISP. You keep your existing regulatory posture.
§ 1

Authentication & identity

OWASP A07 · ASVS V6 · 20 controls covered

Passwords are hashed with scrypt at strong cost parameters, verified in constant time, and checked against known-breached password lists. Two-factor is TOTP, with used codes consumed so they can't be replayed inside their window, plus ten single-use backup codes hashed at rest. Machine-to-machine API keys carry 256 bits of entropy and are stored only as a hash, shown once and never again. Login attempts are throttled per identity and per source IP, shared across every instance so a lockout can't be dodged by hitting another replica.

§ 2

Session management

ASVS V7 · 8 controls covered

Sessions are opaque server-side tokens, hashed at rest, in an HttpOnly, SameSite=Strict, Secure cookie scoped per subdomain. Every session has an absolute maximum lifetime of eight hours and a separate thirty-minute inactivity timeout, whichever expires first. Each authenticated request re-validates the session and slides the inactivity window forward, never past the eight-hour cap, so a stale or idle session can't linger. Users can view their active sessions and revoke them, administrators can terminate a user's sessions, and enabling or disabling two-factor ends all other sessions. Sensitive changes require a fresh two-factor code rather than trusting the existing session.

§ 3

Authorisation & multi-tenant isolation

OWASP A01 · ASVS V8 · the crown-jewel control

Tenant scope is derived from the authenticated caller, never read from the request body or query, and checked against both independently. Isolation is enforced by genuine Postgres row-level security in FORCE mode, which applies even to the table owner, on every tenant table. With no scope set, a query returns zero rows by default. The platform refuses to start in production if the database role could bypass that rule, so the isolation can't be silently switched off. Within a company, roles are a fail-closed allow-list: a new mutating route is denied to read-only users until it's explicitly permitted.

§ 4

Encryption at rest

OWASP A02 · ASVS V11 · 17 controls covered

Sensitive fields, credentials, and signing keys are encrypted with AES-256-GCM at the application layer, before anything reaches the database, so stored bytes are ciphertext even to a full-database read. Each ciphertext is bound to its exact table, column, tenant, and row, so a stolen value can't be relocated to another column or tenant and decrypted. Keys carry an embedded identifier so old data still decrypts through a rotation, and an unknown key identifier throws rather than silently mis-decrypting. The audit-signing key is held separately from the field-encryption key, so one leaked key can't also forge the log.

§ 5

Encryption in transit

ASVS V12

Database connections require verified TLS, and the server refuses to start if TLS is disabled or set not to verify. Outbound traffic to banks and webhook endpoints is HTTPS-only, validates the certificate, is pinned to the pre-resolved address, follows no redirects, and caps the response size. One deliberate exception exists, a single bank certificate-revocation list fetched over plain HTTP and then verified independently by signature.

Online certificate revocation checking and Encrypted Client Hello are not wired; we rely on CA-chain validation plus certificate pinning. Both are Level 3 items.

§ 6

Cryptographic channel security

bank connectivity · ASVS V11

Each bank channel uses the real cryptography the bank requires. SOAP channels use signed and encrypted payloads with RSA-SHA256 signatures, and inbound signatures are certificate-pinned and fail closed on a signer mismatch. EBICS uses DOM-bound XML signatures with anti-signature-wrapping checks. SFTP encrypts to the bank's key with recipient fingerprint pinning and verifies the host key against a pinned fingerprint, refusing an unpinned host in production. Certificate pins carry expiry warnings and fail closed when a pin lapses.

Where a bank still mandates an older primitive, we use it, wrapped in extra integrity and pinning. We don't present the underlying primitive as our choice.

§ 7

Payment authorisation controls

maker-checker · fail-closed

With our built-in approvals, a host-to-host payment is held and released at a single guarded point, evaluated under a row lock so two approvals can't race. The person who created a payment can't approve it, the same person can't approve twice, and the approver must be named in the policy, not merely hold the role. A fresh two-factor code is required at approval. A payment that needs approval with no eligible approver is refused at dispatch rather than parked indefinitely. Platforms that run their own external approval process keep that dual-control in their own system, and we deliver only what they release.

§ 8

Direct-only delivery

signing-oracle prevention

Payments are delivered straight to the customer's bank over their own channel. We never return the signed payment file to the caller. That closes off using the platform as a signing service for instructions that weren't approved: a caller gets a status reference back, never a signed file they could submit elsewhere.

§ 9

Network security & SSRF

ASVS V13 · V15

Every outbound URL is checked against an allow-list and a structural SSRF guard that rejects loopback, private, link-local, and cloud-metadata addresses, along with obfuscated IP literals. Each resolved address is range-checked, the connection is pinned to the validated address to defeat DNS-rebinding between check and connect, and no redirects are followed. Webhook destinations are re-checked at delivery time, not just at registration.

§ 10

File handling

ASVS V5 · 5 controls covered

Permitted file types and size ceilings are defined and enforced, with an ingest cap on inbound files. Compressed files are checked against decompression-bomb expansion. Submitted filenames are validated against path traversal, and account identifiers are masked in any filename that gets served or logged.

§ 11

Web & HTTP hardening

ASVS V3 · 15 controls covered

Responses carry an explicit Content-Security-Policy, frame-ancestors set to none, nosniff, a referrer policy, cross-origin isolation headers, and HSTS with preload in production. There's no JSONP anywhere, authenticated responses are JSON only, and client assets are served same-origin from local bundles. HTTP parameter pollution is rejected, and CSRF protection is bound to the session rather than a bare double-submit, which defeats sibling-subdomain cookie planting.

We don't use the __Host- cookie prefix. That's deliberate: a multi-tenant platform needs domain-scoped cookies across subdomains, which the prefix forbids, so isolation rests on Domain, Secure, and SameSite=Strict instead. Level 2 item, resolved by design.

§ 12

Audit, integrity & non-repudiation

ASVS V16 · 17 of 17 covered

Every state change is written to a journal the database itself refuses to update or delete, enforced by a trigger that fires even for the table owner. Each entry is HMAC-hash-chained to the one before it, keyed per company, so any modification, deletion, insertion, or reorder is detectable, and a live endpoint re-walks the chain and reports the first inconsistent entry. The signing key comes from the key provider, not the database, so an attacker with database write access still can't recompute the chain. We're explicit about the boundary: this is tamper-evidence within our trust boundary, not an external timestamping service.

§ 13

Data protection & retention

ASVS V14 · 10 controls covered

Sensitive data is inventoried and classified, and an approver's national ID number is encrypted, masked to the last four on every read, and resolved in the clear only transiently at file-build time, never logged. Logs are scrubbed by both key name and value shape, and metrics carry no tenant identifiers or personal data. Retention is classified per data type, with erasure supported for the right-to-be-forgotten, and responses are set not to cache sensitive content.

§ 14

Secure configuration & coding

ASVS V13 · V15 · 32 controls covered across both

The platform treats any ambiguous environment as production and fails closed. It won't boot without verified database TLS, an independent audit key of sufficient strength, and a non-bypassable isolation role. Debug modes and directory listings are off in production, the HTTP TRACE method is unsupported, and monitoring endpoints are gated behind a token. Input is validated with strict schemas against mass-assignment and type confusion, a software bill of materials is generated in CI, dependencies are audited at a blocking threshold, and third-party CI actions are pinned to specific commits.

Standards alignment

Used as a checklist lens, not a certification claim. Of the 275 Level 2 and Level 3 requirements in OWASP ASVS v5, 89 don't apply to our architecture, leaving 186 in scope. 157 are verified in code today. The rest are 20 partials, usually where the control is enforced but the written documentation is still catching up, and 9 open items, each a deliberate trade-off or a notification feature rather than a broken control. We designed against ISO 27001 Annex A and the SOC 2 control set as well. To be exact: SOC 2 and ISO 27001 certification, and independent penetration testing, are planned and not yet done. We'd rather show you the real coverage than imply a badge we haven't earned.

Go deeper

Request the full security package.

For your security review, we share the OWASP ASVS Level 2 and 3 coverage matrix, the control-to-evidence mapping, and our data-flow and funds-handling statement. The DPA, sub-processor list, and privacy policy live on our legal page. Tell us where to send the package.

Inspect the audit log and approvals yourself.