FIPS 140-3
flagd is released in two variants.
The standard build is the default and uses the ordinary Go cryptography. The FIPS build is compiled against the Go Cryptographic Module v1.0.0, which holds NIST CMVP validation certificate #5247 and CAVP certificate A6650, and runs it in the FIPS 140-3 approved mode. Both variants are published for flagd and flagd-proxy on every release.
The validation covers the Go Cryptographic Module. flagd consumes the module and has not been submitted to CMVP. A FIPS-mode deployment may still need further controls to satisfy FedRAMP, DoD SRG, CMMC or a similar programme; those determinations depend on the whole system and its assessment.
The scope is cryptography performed inside the flagd process. It excludes TLS terminated by a proxy or service mesh in front of flagd, the platform and container runtime, and operator-supplied key material. flagd performs no authentication or authorization on any endpoint and expects to run inside a trust boundary.
Getting the FIPS build
Container images carry a -fips tag suffix:
Release archives carry it in the product position, so globs that match the standard artifacts do not pick up the FIPS ones:
To build one:
GOFIPS140=v1.0.0 selects the frozen, certified module snapshot and makes the binary default to GODEBUG=fips140=on.
Use the literal version: the certified and inprocess aliases resolve differently per Go toolchain, and on Go 1.26 inprocess points at module v1.26.0, which is still pending CMVP review.
The fips140 build tag is what makes the binary require that module rather than merely report on it.
The two belong together, and a binary built with the tag but without GOFIPS140 refuses to start rather than presenting itself as a FIPS build.
Verifying
The build settings are recorded in the binary's runtime/debug.BuildInfo and survive -trimpath and -ldflags "-s -w".
v1.0.0-c2097c7c uniquely identifies the module snapshot.
fips140 is flagd's own tag; fips140v1.0 is added by the Go toolchain.
The running process reports the same state, both from the version command and in its startup log.
flagd: v0.16.2 (a1b2c3d), built at: 2026-08-28
build variant: fips
FIPS 140-3 mode: enabled (Go Cryptographic Module v1.0.0, GOFIPS140=v1.0.0-c2097c7c)
The standard build reports build variant: standard and FIPS 140-3 mode: disabled.
Enforcement
FIPS mode is fixed at process start and is turned off with GODEBUG=fips140=off.
A FIPS build started that way refuses to run, so a stray GODEBUG cannot quietly drop a deployment out of approved mode.
There is no flag to override this: a binary that carries the fips140 tag either runs the certified module or does not run.
The standard build performs no such check and is unaffected by GODEBUG=fips140=off.
TLS restrictions
These apply to the FIPS build only.
In FIPS mode crypto/tls will not negotiate a protocol version, cipher suite, curve or signature algorithm outside the approved set.
| Parameter | Permitted |
|---|---|
| Protocol versions | TLS 1.2, TLS 1.3 |
| Key exchange | X25519MLKEM768, SecP256r1MLKEM768, SecP384r1MLKEM1024, P-256, P-384, P-521 |
| TLS 1.3 cipher suites | TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384 |
| TLS 1.2 cipher suites | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 |
| Peer certificates | RSA 2048 bits or larger, ECDSA P-256/P-384/P-521, Ed25519 |
Excluded: SHA-1, 3DES, RC4, ChaCha20-Poly1305, plain X25519, RSA PKCS #1 v1.5 key transport, TLS 1.0 and TLS 1.1.
Moving from the standard build to the FIPS build
Clients that only offer ChaCha20-Poly1305 or plain X25519 will fail the handshake. Server certificates with RSA keys under 2048 bits are rejected. Check your clients and certificates before switching.
This applies to flagd's outbound sync connections as well as to the TLS it terminates. A flag source, or a Kubernetes API server, that negotiates outside the approved set will not be reachable from the FIPS build.
The policy filter lives in crypto/tls, which sits outside the validated module boundary and tracks the Go toolchain version.
flagd pins its toolchain so the negotiable set stays fixed across releases.
Platform support
Go's FIPS 140-3 mode is unavailable on wasm, windows/386, openbsd and aix.
A windows/386 build compiles but panics at startup, so that binary is no longer released.
linux/386 is no longer released either. FIPS mode runs there, but 32-bit x86 Linux is not among the operating environments the module was validated on, so a build for it could not carry the same claim.
Cryptography used by flagd
These are security functions, all serviced by the validated module.
| Algorithm | Purpose | Location |
|---|---|---|
| TLS 1.2/1.3 (AES-GCM, ECDHE, HKDF, HMAC) | Evaluation and sync transport security | flagd/pkg/service/flag-evaluation/connect_service.go, flagd/pkg/service/flag-sync/sync_service.go, core/pkg/sync/grpc/credentials/builder.go |
| ECDSA, RSA-PSS, RSA PKCS #1 v1.5, Ed25519 | TLS certificate and signature verification | crypto/tls, crypto/x509 |
| CTR_DRBG | Random number generation | crypto/rand |
The remaining uses are not security functions, so no approved-algorithm requirement applies to them.
| Algorithm | Purpose | Location |
|---|---|---|
| SHA3-256 | Detecting whether a fetched flag configuration changed | core/pkg/utils/hash.go |
| SHA-256 | OFREP SSE ETag fingerprint |
flagd/pkg/service/flag-evaluation/ofrep/sse/tracker.go |
| MurmurHash3-32 | Fractional rollout bucketing | core/pkg/evaluator/fractional.go |
| FNV-1a 32 | Poll interval jitter offset | core/pkg/sync/internal/polling/poller.go |
| UUIDv4 | Default internal flag set identifier | core/pkg/store/query.go |
SHA3-256 and SHA-256 are approved algorithms and come from the validated module; flagd uses them for change detection and HTTP cache validation.
MurmurHash3 assigns an evaluation context to a bucket for percentage-based rollouts. The fractional operation specification mandates it so that every flagd provider, in every language, assigns the same unit to the same bucket. Predicting or colliding it reveals only which variant a context receives, which evaluating the flag already tells you.
FNV-1a spreads polling across the configured interval to avoid a thundering herd.
UUIDv4 is an internal index key that is never exposed externally, and its entropy comes from crypto/rand.
Non-approved algorithms in the dependency tree
core/pkg/sync/blob/blob_sync.go links the gocloud.dev drivers for S3, GCS and Azure Blob so those sync sources work out of the box.
Those SDKs pull non-approved primitives into the link closure:
golang.org/x/crypto/pkcs12and its RC2 implementation, viaazidentitygolang.org/x/crypto/chacha20poly1305, viagoogle/s2a-gocrypto/md5andcrypto/sha1, via gocloud'sContent-MD5handling, the AWS checksum and SSO credential paths, and Azure AD MSAL
The standard library contributes crypto/des, crypto/rc4, crypto/sha1 and crypto/md5 on its own account, through crypto/tls and crypto/x509 legacy parsing, plus crypto/mldsa for post-quantum certificate signatures.
The FIPS policy filter keeps that set out of negotiation.
flagd calls none of these for its own security functions. They run only on cloud provider credential and object integrity paths, where the SDKs need them for protocol compatibility, and the providers offer FIPS-validated and FedRAMP-authorized endpoints. Data in transit on those paths is protected by TLS from the validated module.
The full closure is recorded in fips-crypto-closure.txt, which CI regenerates and diffs, so any change to it has to be reviewed.
Keys and secrets
flagd generates, wraps, stores and zeroizes no cryptographic keys.
TLS private keys are read from operator-supplied PEM paths (--server-cert-path, --server-key-path) via tls.LoadX509KeyPair.
OAuth2 client credentials and static Authorization headers for the HTTP sync source are read from configuration or mounted files and held in memory as Go strings, which cannot be zeroized.
Protect them with file permissions, a secret manager and short credential lifetimes.