composer/ca-bundle
Find the system CA root bundle path for TLS verification, with automatic fallback to a bundled Mozilla CA file. Simple API for curl, PHP streams, and HTTP clients like Guzzle; includes CA file validation and cache reset utilities.
Installation:
composer require composer/ca-bundle
Add to composer.json under require if using a monorepo or custom setup.
First Use Case: Resolve the CA bundle path for a cURL request:
$caPath = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
curl_setopt($curl, CURLOPT_CAINFO, $caPath); // or CURLOPT_CAPATH if dir
Where to Look First:
\Composer\CaBundle\CaBundle (static methods).getSystemCaRootBundlePath() (primary entry point).getBundledCaBundlePath() (fallback to Mozilla’s cacert.pem).HTTP Client Integration:
$client = new \GuzzleHttp\Client([
\GuzzleHttp\RequestOptions::VERIFY => \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath(),
]);
stream_context_create:
$context = stream_context_create([
'ssl' => [
'cafile' => \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath(),
],
]);
file_get_contents('https://example.com', false, $context);
Environment-Specific Overrides:
bind):
$app->bind(\Composer\CaBundle\CaBundle::class, function () {
return \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
});
$caPath = getenv('CA_BUNDLE_PATH') ?? \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
Validation Workflows:
if (\Composer\CaBundle\CaBundle::isOpensslParseSafe()) {
$cert = \Composer\CaBundle\CaBundle::validateCaFile('/path/to/cert.pem');
}
Testing:
\Composer\CaBundle\CaBundle::reset(); // Clear static cache
\Composer\CaBundle\CaBundle::setCaPath('/path/to/test/cacert.pem'); // If extending
$caPath = \Composer\CaBundle\CaBundle::getBundledCaBundlePath();
CI/CD Pipelines:
# .github/workflows/test.yml
- name: Install dependencies
run: composer require composer/ca-bundle
- name: Run tests with CA bundle
run: php tests/integration/ssl_test.php
RUN curl -sSL https://curl.se/ca/cacert.pem -o /usr/local/share/ca-certificates/cacert.pem \
&& update-ca-certificates
Legacy System Migration:
/etc/ssl/certs/ca-certificates.crt) with the dynamic resolver:
// Before
curl_setopt($curl, CURLOPT_CAINFO, '/etc/ssl/certs/ca-certificates.crt');
// After
curl_setopt($curl, CURLOPT_CAINFO, \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath());
Multi-Cloud Deployments:
$caPath = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
// Works on Lambda (fallback to bundled), GCP (system path), or Kubernetes (host-mounted).
Static Cache:
\Composer\CaBundle\CaBundle::reset();
OpenSSL Parsing Safety:
openssl_x509_parse() may not be available or safe on all PHP builds (e.g., disabled for security). Always check:
if (!\Composer\CaBundle\CaBundle::isOpensslParseSafe()) {
throw new \RuntimeException('OpenSSL parsing is not supported.');
}
Path Format Ambiguity:
/etc/ssl/certs/ca-certificates.crt) or a directory path (e.g., /etc/ssl/certs/). Always check is_dir():
$caPath = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
if (is_dir($caPath)) {
curl_setopt($curl, CURLOPT_CAPATH, $caPath); // Directory
} else {
curl_setopt($curl, CURLOPT_CAINFO, $caPath); // File
}
Bundled CA Updates:
cacert.pem is updated quarterly (see releases). If you rely on the fallback, ensure your app can handle updates without breaking:
// Example: Validate the bundled CA on startup
$bundledPath = \Composer\CaBundle\CaBundle::getBundledCaBundlePath();
if (!file_exists($bundledPath)) {
throw new \RuntimeException('Bundled CA certificate missing!');
}
PHP Version Deprecations:
Open_Basedir Restrictions:
open_basedir is enabled, the bundled CA path may be inaccessible. Test in restricted environments:
if (!is_readable(\Composer\CaBundle\CaBundle::getBundledCaBundlePath())) {
throw new \RuntimeException('CA bundle inaccessible due to open_basedir restrictions.');
}
Log CA Paths:
$caPath = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
\Log::debug('Using CA path:', ['path' => $caPath, 'is_dir' => is_dir($caPath)]);
Validate Certificates:
openssl CLI to verify the resolved path:
openssl verify -CApath /path/to/resolved/ca /path/to/cert.pem
Check System Paths:
$paths = [
'/etc/ssl/certs/ca-certificates.crt', // Debian/Ubuntu
'/etc/pki/tls/certs/ca-bundle.crt', // RHEL/CentOS
'/usr/local/etc/openssl/cert.pem', // macOS (Homebrew)
'/etc/ssl/cert.pem', // macOS (default)
];
Fallback Behavior:
// Simulate a missing system CA
\Composer\CaBundle\CaBundle::reset();
$caPath = \Composer\CaBundle\CaBundle::getBundledCaBundlePath();
Custom CA Paths:
class CustomCaBundle extends \Composer\CaBundle\CaBundle {
public static function getSystemCaRootBundlePath(): string {
$customPath = getenv('CUSTOM_CA_PATH');
return $customPath ?? parent::getSystemCaRootBundlePath();
}
}
Override Trust Stores:
How can I help you explore Laravel packages today?