Configure trusted HTTPS certificates in Java and Python

Repair chain and hostname validation with an explicit application trust configuration instead of accepting every certificate.

Best practices
Illustration of software components, data, and application workflows

Accepting every certificate removes a critical part of HTTPS server authentication. Encryption alone does not tell you whether the encrypted peer is the intended service. Use a trusted public or private CA and keep hostname verification enabled.

Identify the failed check

Inspect the actual error before changing trust settings. An unknown issuer, missing intermediate, expired certificate, incorrect hostname, and wrong system clock need different fixes.

Certificate-chain trust and hostname matching are related but separate checks. A Java client may still check hostnames after its trust manager has been replaced, but accepting arbitrary chains remains unsafe: an attacker can create a certificate naming the target host. Disabling both checks makes the problem worse.

Avoid Requests verify=False, accept-all trust managers, and permissive hostname verifiers. For development, use a controlled test CA and a certificate whose subject alternative names match the addresses used by the test.

Set Python trust explicitly

Requests can use a public CA bundle or a verified organization-specific bundle:

import certifi
import requests

response = requests.get(
    "https://example.com",
    verify=certifi.where(),
    timeout=10,
)
response.raise_for_status()

For a private endpoint, use verify="/path/to/approved-company-ca-bundle.pem". Obtain that bundle through a trusted PKI channel and verify its fingerprint; certifi's public roots do not include every enterprise CA. A Requests timeout is not a guaranteed deadline for the entire download.

For a standard-library client, extend the default trust set with an approved CA:

import ssl
import urllib.request

context = ssl.create_default_context()
context.load_verify_locations(cafile="/path/to/company-root-ca.pem")
with urllib.request.urlopen(
    "https://internal-api.example.com", context=context, timeout=10
) as response:
    data = response.read()

The default context retains chain and hostname checks. Updating certifi can refresh public roots when the client uses it, but cannot fix a wrong hostname or repair a server that sends an incomplete chain in every environment.

Use a deliberate Java truststore

After independently verifying the CA certificate, import it into an application truststore. This example chooses PKCS12 explicitly and lets keytool prompt for the password:

keytool -importcert -alias internal-ca \
  -file internal-ca.crt \
  -keystore application-truststore.p12 -storetype PKCS12

For clients using the JVM's default JSSE trust configuration, point the process at that store:

java -Djavax.net.ssl.trustStore=/path/to/application-truststore.p12 \
     -Djavax.net.ssl.trustStoreType=PKCS12 \
     -jar app.jar

Supply any required truststore password through the deployment's protected JVM configuration mechanism. Avoid committing it or exposing it in a shared command line. A custom truststore normally replaces the default store used by that configuration; include every CA the application needs. A client with its own SSLContext or trust manager may not use these JVM defaults.

The server should present its leaf certificate and required intermediates; the client trusts an approved anchor. Do not blindly import every certificate returned by a failing endpoint or modify a different JDK's cacerts file.

FAQ

Can I trust just my self-signed certificate?

A deliberately verified self-signed certificate can be an explicit trust anchor where the client supports that configuration. That is narrower than accepting every certificate. Plan certificate renewal and retain hostname checks.

Why does Java still report PKIX errors?

Check the actual runtime JDK, selected truststore, client SSL configuration, validity period, and chain. A successfully imported certificate in an unused store has no effect.

Should I suppress InsecureRequestWarning?

Fix the request's trust configuration instead. A warning filter does not restore server authentication. Keep test CA private keys out of shared repositories and limit test trust to the intended environments.

After fixing the client, an independently configured Guance HTTP synthetic test can check reachability and HTTPS behavior. Keep certificate verification enabled there too; private CA trust and client-certificate authentication are different settings.

References: Requests TLS verification, Python SSL contexts, Java JSSE trust configuration, Java keytool.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting