Skip to content

fix: avoid FIPS 140-only panic when parsing sops PGP private keys - #1846

Merged
joaopapereira merged 1 commit into
carvel-dev:developfrom
sameerforge:topic/sameerkh/fips140-sops-pgp-fingerprint
Aug 13, 2026
Merged

fix: avoid FIPS 140-only panic when parsing sops PGP private keys#1846
joaopapereira merged 1 commit into
carvel-dev:developfrom
sameerforge:topic/sameerkh/fips140-sops-pgp-fingerprint

Conversation

@sameerforge

@sameerforge sameerforge commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Problem
When kapp-controller is built with Go's native FIPS 140-3 module and run with strict enforcement (GODEBUG=fips140=only), using the sops template's PGP backend panics while loading the user's private key:
panic: crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode

This happens on every reconcile of an App that uses spec.template[].sops.pgp, making the PGP decryption path entirely unusable under strict FIPS mode.

Root cause
gpgKeyring.Write (pkg/template/sops.go) calls golang.org/x/crypto/openpgp.ReadArmoredKeyRing to parse the user-supplied private key. Parsing an OpenPGP key packet unconditionally computes its RFC 4880 V4 key fingerprint using SHA-1, as part of just building the in-memory key structure — regardless of whether that fingerprint is ever used for anything security-sensitive. SHA-1 is not an approved algorithm under FIPS 140-3, so under strict enforcement this call panics rather than returning an error.

Fix
Wrap the openpgp.ReadArmoredKeyRing call in crypto/fips140.WithoutEnforcement (available since Go 1.26), which scopes the enforcement relaxation to just that one call rather than disabling FIPS enforcement for the process:

This is safe because the fingerprint computed here is used only as a local identifier while loading the key for later use by the external sops binary — it does not verify or establish trust in any signature, so relaxing enforcement for this narrow, non-security parse step does not weaken any FIPS security guarantee.

WithoutEnforcement is a no-op everywhere except GODEBUG=fips140=only: it short-circuits to a direct call in non-FIPS builds and under fips140=on/off/unset, so this change has no effect outside of strict FIPS mode.

Testing

  • Added TestGpgKeyringWrite_UnderFIPS140Only in pkg/template/sops_test.go, which loads a private PGP key and writes it out via gpgKeyring.Write. Confirmed it panics on the pre-fix code under GODEBUG=fips140=only and passes with the fix applied.
  • Verified the fix behaves identically to the pre-fix code under GODEBUG=fips140=on/off/unset and in non-FIPS builds — no behavioral change outside strict mode.
  • Ran the existing pkg/template unit suite with and without GODEBUG=fips140=only; no other regressions.

Parsing any OpenPGP key packet (golang.org/x/crypto/openpgp) unconditionally
computes its RFC 4880 V4 fingerprint using SHA-1 as part of the wire-format
parse itself, in PublicKey.setFingerPrintAndKeyId. Under Go's native FIPS
140-3 module running with GODEBUG=fips140=only, that SHA-1 call panics -
so gpgKeyring.Write panics on every App reconcile that uses the sops PGP
template backend (AppTemplateSops.PGP), before sops ever gets a chance to
decrypt anything.

That fingerprint is only used here as an OpenPGP key identifier while
loading a user-supplied private key for later use by the external sops
binary; it is not used to verify or trust any signature. Since Go 1.26,
crypto/fips140.WithoutEnforcement lets us relax FIPS enforcement for just
this parse call without weakening enforcement anywhere else in the binary,
including the rest of gpgKeyring.Write - the subsequent Serialize calls
were confirmed (by removing the wrapper locally) not to need it, since
serializing already-parsed packets performs no further hashing.

The sops Age backend is unaffected; ReadArmoredKeyRing is only reached
from the PGP branch.

Adds TestGpgKeyringWrite_UnderFIPS140Only, which reproduces the panic
pre-fix under GOFIPS140=v1.0.0 GODEBUG=fips140=only.

Signed-off-by: Sameer <sameer.khan@broadcom.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Sameer <sameer.khan@broadcom.com>

@joaopapereira joaopapereira left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm

@joaopapereira
joaopapereira merged commit fa7964c into carvel-dev:develop Aug 13, 2026
13 checks passed
@github-project-automation github-project-automation Bot moved this to Closed in Carvel Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants