getCACertificates function

List<String>? getCACertificates()

Load CA certificates for TLS connections.

Since setting ca on an HTTPS agent replaces the default certificate store, we must always include base CAs when returning.

Returns null when no custom CA configuration is needed, allowing the runtime's default certificate handling to apply.

Behavior:

  • Neither NODE_EXTRA_CA_CERTS nor --use-system-ca set: null (runtime defaults)
  • NODE_EXTRA_CA_CERTS only: extra cert file contents
  • --use-system-ca: system CAs + extra cert file

Implementation

List<String>? getCACertificates() {
  if (_caCertsCacheInitialized) return _caCertsCache;
  _caCertsCacheInitialized = true;

  final useSystemCA =
      _hasNodeOption('--use-system-ca') || _hasNodeOption('--use-openssl-ca');
  final extraCertsPath = Platform.environment['NODE_EXTRA_CA_CERTS'];

  // If neither is set, return null (use runtime defaults)
  if (!useSystemCA && (extraCertsPath == null || extraCertsPath.isEmpty)) {
    return null;
  }

  final certs = <String>[];

  // When useSystemCA is true but we're in Dart, we don't have direct
  // access to system CAs like Node's tls.rootCertificates.
  // In a Flutter/Dart app, the system CA store is used automatically.
  // We only handle the extra certs path.

  if (extraCertsPath != null && extraCertsPath.isNotEmpty) {
    try {
      final extraCert = File(extraCertsPath).readAsStringSync();
      certs.add(extraCert);
    } catch (error) {
      stderr.writeln(
        'CA certs: Failed to read NODE_EXTRA_CA_CERTS file '
        '($extraCertsPath): $error',
      );
    }
  }

  _caCertsCache = certs.isNotEmpty ? certs : null;
  return _caCertsCache;
}