Last updated: August 21, 2026
This review is performed line-by-line against FIPSign's real, running source code — not a questionnaire or a template checklist. Each item below was verified by reading the implementation that handles it, cross-referenced against the relevant OWASP ASVS v4.0 requirement.
The cryptographic core (token signing, certificate authority, and key storage) is held to ASVS Level 3 — the standard's highest bar, intended for applications where a cryptographic failure has serious consequences. The rest of the API and dashboard are held to Level 2.
Where something doesn't meet the bar, it's listed as a limitation below, not omitted. Where something has been checked and fixed, it's listed as resolved. Nothing is marked as verified without having been read and tested against real code.
The dashboard is a thin client that never makes an authorization decision on its own — every operation is independently re-verified inside the Worker itself, regardless of what a request sends or a screen displays. Which project, key, or certificate an operation applies to is always derived server-side from the authenticated session or API key, never trusted from a request body.
Every API key, certificate, and signed token belongs to exactly one project, and every operation that touches one of these resources verifies ownership before doing anything else. For Mandate — FIPSign's bounded-authorization primitive for agents and services — this goes further than a check: the resource's own storage identity is derived from the requesting project, so a key belonging to one project literally cannot address a Mandate that belongs to another. Ownership failures return a generic not-found response rather than confirming to an unauthorized caller that a resource even exists.
Session cookies use SameSite=Strict together with a strict origin allowlist — one of the strongest anti-CSRF combinations a browser offers natively. Requesting a sign-in code, which is also how new accounts get created, is rate-limited independently by email address and by IP address, so the email channel itself can't be turned into a mass-mailing vector even by an attacker rotating across many addresses.
FIPSign's internal administrative operations — adjusting endpoint pricing, account limits, and token packs — are protected by a single static secret, checked with a constant-time comparison and rate-limited per IP, but not by multi-factor authentication. This isn't a login screen exposed to the public: it has no presence anywhere in the developer-facing dashboard and is invoked directly, by us, from our own infrastructure.
We weighed adding an interactive second factor here against the friction it would add to what is today a purely programmatic, single-operator flow, and judged the current protection proportionate — this surface never touches signing keys or certificate authority material. We'll revisit this if that scope ever changes.
Digital signatures use ML-DSA, the NIST-standardized post-quantum signature algorithm (FIPS 204). Data encrypted at rest — private signing keys, certificate authority material, and webhook secrets — uses AES-256-GCM, an authenticated encryption standard. Both are public, independently vetted algorithms; no custom or proprietary cryptography is used anywhere in the system.
Private keys never leave the server and are never returned in any API response. They are decrypted in memory only for the instant a signature is being produced, and re-encrypted before being written to storage. Every encryption operation uses a fresh, cryptographically random value — no key material or randomness is ever reused across operations.
The system supports rotating its master encryption key without downtime or data loss: newly written data can be encrypted under a new key while existing data remains readable under the old one, until a verified migration completes and the old key is retired.
FIPSign does not store regulated personal, health, or financial data. The payloads customers sign are opaque to us — we don't inspect, log, or retain their contents beyond what's needed to serve the request.
The underlying post-quantum signature library FIPSign depends on does not yet implement dedicated countermeasures against timing or power-based side-channel attacks. This is a limitation of the current generation of post-quantum cryptography implementations across the JavaScript/WebAssembly ecosystem generally — not something specific to our integration — and upstream maintainers are actively researching how to close it.
Exploiting this class of attack would require an adversary with direct, low-level measurement access to the signing process itself — not a capability available to a remote network attacker. Signing keys never leave server memory regardless. We're tracking upstream progress and will update this page as hardened implementations become available.
Every field the API accepts — token payloads, certificate subjects and public keys, mandate scopes, two-factor codes — is checked against an explicit type, an allowed set of values where one exists, and a maximum length, before anything else happens with it. Custom metadata fields are capped on total size, not just count, so a single request can't be used to force a disproportionate amount of signing computation. Fields with no legitimate reason to vary in size — like a certificate's public key or a signed token's cryptographic signature — are checked against their exact expected size for the algorithm in use, not just an upper bound.
Every database query in the system is built with parameterized placeholders and bound values — user-supplied data is never concatenated into a query string. The one query that composes its structure dynamically only ever assembles it from a fixed, hardcoded set of column names; the values themselves always go through the same parameter binding as everything else.
Webhook URLs are validated against private, loopback, and link-local address ranges both when they're accepted and again immediately before every actual delivery attempt, so a destination that resolves differently over time can't quietly become an internal one.
No part of the system evaluates strings as code — there is no eval, no dynamic Function construction, and no template engine that interprets user-supplied syntax anywhere in the codebase. Several classical injection categories — LDAP, XML/XPath, OS command injection — don't have a foothold here at all: the system has no LDAP directory, does no XML parsing, and runs in an isolated compute environment with no shell or filesystem access to begin with.
FIPSign has no password authenticator in the system — accounts are created and accessed exclusively through email-verified one-time codes. There is nothing to leak, guess, reuse across sites, or store insecurely, and no default or shared account exists anywhere in the codebase.
Each sign-in code is generated fresh per request using a cryptographically secure random number generator, expires after 10 minutes, and can only be used once — requesting or using a code invalidates any earlier one for that account. Only a cryptographic hash of the code is ever stored; the code itself is never persisted anywhere. Verification is rate-limited per account, enforced atomically so it can't be bypassed by concurrent requests.
Developers can enable a second factor (TOTP, compatible with Google Authenticator, Authy, and similar apps) on top of the email code. Once enabled, signing in requires both the current email code and the current authenticator code before a session is created — the two are additive, not alternatives. Ten single-use backup codes are issued at setup in case the authenticator device is lost, and every enable/disable action requires proof of the current factor, not just an active session.
API keys used to call the signing API are generated with 256 bits of randomness and hashed before storage — FIPSign itself never has access to the raw key again after the moment it's created. Revoking a key takes effect immediately, with no caching window.
The email sign-in code remains a required first step for every account, including ones with two-factor authentication enabled — the authenticator code is an additional step on top, not an alternative offered instead. Developers who haven't enabled two-factor authentication rely on the email code alone.
This is a deliberate trade-off, not an unresolved gap: requiring a stronger factor before account creation would add friction at the exact moment a new developer is deciding whether to try FIPSign at all — and the developer platforms this product is built alongside make the same choice for their own sign-up. We mitigate the residual risk instead: sign-in sessions are short-lived, verification attempts are tightly rate-limited, and the dashboard never exposes signing key material regardless of how a session was authenticated. Two-factor authentication is available today, and we recommend enabling it.
This review is ongoing. As each OWASP Top 10 category reaches full, verified coverage, it's added below — never partially, and never before it's actually done.
For technical due diligence, a deeper written breakdown, or to report a security concern, contact us at hello@fipsign.dev.