Homebrew/homebrew-core · error · RuntimeException

Failed to initialize non-FIPS provider

Error message

Failed to initialize non-FIPS provider

What it means

RuntimeException thrown by the patched org.sonatype.nexus.crypto.internal.CryptoHelperImpl.loadNonFipsProvider() (patch hunk carried at Formula/n/nexus.rb:200) when it cannot reflectively load and instantiate org.bouncycastle.jce.provider.BouncyCastleProvider. The provider is deliberately loaded through an isolated URLClassLoader (bcprov + bcutil only, parent=null) so that bc-fips classes, which share the org.bouncycastle.crypto.* package namespace, cannot interfere. The catch clause covers ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException and IllegalAccessException, so any mismatch between the expected class/jar layout and reality aborts crypto initialization.

Source

Thrown at Formula/n/nexus.rb:200

index dfeb6f0..38e067c 100644
--- a/public/common/components/nexus-crypto/src/main/java/org/sonatype/nexus/crypto/internal/CryptoHelperImpl.java
+++ b/public/common/components/nexus-crypto/src/main/java/org/sonatype/nexus/crypto/internal/CryptoHelperImpl.java
@@ -87,8 +87,25 @@ public class CryptoHelperImpl
   }
 
   private static void loadNonFipsProvider() {
-    // BouncyCastleProvider must be set as the last provider
-    Security.addProvider(new BouncyCastleProvider());
+    try {
+      Class<?> providerClass =
+          getNonFipsClassLoader().loadClass("org.bouncycastle.jce.provider.BouncyCastleProvider");
+      Provider provider = (Provider) providerClass.getConstructor().newInstance();
+      // BouncyCastleProvider must be set as the last provider
+      Security.addProvider(provider);
+    }
+    catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException
+        | InstantiationException | IllegalAccessException e) {
+      throw new RuntimeException("Failed to initialize non-FIPS provider", e);
+    }
+  }
+
+  private static URLClassLoader getNonFipsClassLoader() {
+    // Load bcprov and bcutil in an isolated classloader to prevent bc-fips classes
+    // (which share org.bouncycastle.crypto.* package names) from interfering.
+    URL bcprovUrl = BouncyCastleProvider.class.getProtectionDomain().getCodeSource().getLocation();
+    URL bcutilUrl = org.bouncycastle.util.Arrays.class.getProtectionDomain().getCodeSource().getLocation();
+    return new URLClassLoader(new URL[]{bcprovUrl, bcutilUrl}, null);
   }
 
   private static void loadFipsProvider() {
diff --git a/public/common/components/nexus-scheduling/src/main/java/org/sonatype/nexus/scheduling/internal/NoopRecoveryModeService.java b/public/common/components/nexus-scheduling/src/main/java/org/sonatype/nexus/scheduling/internal/NoopRecoveryModeService.java
new file mode 100644
index 0000000..9279594
--- /dev/null
+++ b/public/common/components/nexus-scheduling/src/main/java/org/sonatype/nexus/scheduling/internal/NoopRecoveryModeService.java
@@ -0,0 +1,26 @@

View on GitHub (pinned to c0cb250747)

Solutions

  1. Read the wrapped cause first: log/inspect getCause() (and the nested cause chain) — ClassNotFoundException points to a missing/wrong jar, InvocationTargetException to a constructor failure inside the isolated loader.
  2. Verify both jars on the runtime classpath actually contain the classes used for code-source discovery: jar tf bcprov-*.jar | grep 'jce/provider/BouncyCastleProvider.class' and jar tf bcutil-*.jar | grep 'util/Arrays.class'; fix the version pair if either is missing.
  3. If the constructor fails because it references classes outside the two jars, extend the URL[] in getNonFipsClassLoader() with the missing jar(s), or pass a suitable parent classloader instead of null.
  4. Ensure non-FIPS bcprov/bcutil are present even when bc-fips is deployed, and that the non-FIPS and FIPS artifact versions are the pair Nexus expects; do not shade/relocate the BouncyCastle jars for this deployment.
  5. Guard getLocation() results for null and fail with an explicit message naming the unresolved class before building the URLClassLoader.

Example fix

// before
private static URLClassLoader getNonFipsClassLoader() {
  URL bcprovUrl = BouncyCastleProvider.class.getProtectionDomain().getCodeSource().getLocation();
  URL bcutilUrl = org.bouncycastle.util.Arrays.class.getProtectionDomain().getCodeSource().getLocation();
  return new URLClassLoader(new URL[]{bcprovUrl, bcutilUrl}, null);
}

// after
private static URLClassLoader getNonFipsClassLoader() {
  URL bcprovUrl = requireCodeSource(BouncyCastleProvider.class);
  URL bcutilUrl = requireCodeSource(org.bouncycastle.util.Arrays.class);
  return new URLClassLoader(new URL[]{bcprovUrl, bcutilUrl}, null);
}

private static URL requireCodeSource(Class<?> clazz) {
  URL url = clazz.getProtectionDomain().getCodeSource().getLocation();
  if (url == null) {
    throw new IllegalStateException("No code source for " + clazz.getName() + "; cannot build isolated BC classloader");
  }
  return url;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Run before Nexus/crypto init to confirm the isolated BC load will succeed
static boolean nonFipsProviderLoadable() {
  URL bcprov = BouncyCastleProvider.class.getProtectionDomain().getCodeSource().getLocation();
  URL bcutil = org.bouncycastle.util.Arrays.class.getProtectionDomain().getCodeSource().getLocation();
  if (bcprov == null || bcutil == null) return false;
  try (URLClassLoader cl = new URLClassLoader(new URL[]{bcprov, bcutil}, null)) {
    return cl.loadClass("org.bouncycastle.jce.provider.BouncyCastleProvider").getConstructor() != null;
  } catch (ReflectiveOperationException | RuntimeException e) {
    return false;
  }
}

Try / catch

// CryptoHelperImpl init runs in a static block, so catch the wrapper AND the static-init error
try {
  // ... trigger crypto helper initialization ...
} catch (ExceptionInInitializerError e) {
  Throwable root = unwrap(e.getException()); // walk getCause() chain
  if (root instanceof ClassNotFoundException) { /* bcprov/bcutil jar missing or version mismatch */ }
  else if (root instanceof InvocationTargetException && root.getCause() != null) { /* provider constructor failed inside isolated loader */ }
  throw new IllegalStateException("Non-FIPS BC provider init failed: " + root, root);
} catch (RuntimeException e) { // if not via static init
  throw new IllegalStateException("Non-FIPS BC provider init failed: " + unwrap(e), e);
}

Prevention

When it happens

Trigger: Calling the static initialization path of CryptoHelperImpl (i.e. Nexus startup / brew install nexus smoke run) when: (a) bcprov or bcutil jar is missing from the classpath so getNonFipsClassLoader() cannot resolve a code-source URL; (b) the BC version's jar split differs (org.bouncycastle.util.Arrays moved between bcprov and bcutil across releases) so the two URLs point at jars that do not contain the expected entries; (c) the provider constructor throws (InvocationTargetException) because it needs a class outside the two-jar, parentless loader; (d) code source getLocation() returns null (module/jrt or custom loader); (e) a bc-fips-only deployment where BouncyCastleProvider (non-FIPS) does not exist at all.

Common situations: Upgrading BouncyCastle versions where classes relocate between bcprov/bcutil; mixing bc-fips artifacts with regular bcprov/bcutil on one classpath (the exact interference this patch isolates against); shaded or relocated uber-jars where code-source URLs no longer match the expected jars; trimmed distributions that drop bcutil; running under a JRE/container where the protection domain reports no location. Note a hard NoClassDefFoundError on the BouncyCastleProvider.class reference itself escapes the catch clause and surfaces raw.

Related errors


AI-assisted analysis of Homebrew/homebrew-core@c0cb250747 (2026-08-21). Data as JSON: /api/errors/b632f15c77543ed0. Report an issue: GitHub.