passbolt/passbolt_api · error · BadRequestException

Invalid value provided in `passbolt.security.sso.sslCafile`…

Error message

Invalid value provided in `passbolt.security.sso.sslCafile` config

What it means

SsoHttpClientFactory::resolveVerify() maps passbolt.security.sso.sslVerify/sslCafile config onto Guzzle's 'verify' option. If sslVerify is truthy and a custom CA bundle is configured, sslCafile must be a string path; any other value (array, true, int, non-empty-but-invalid type) throws this BadRequestException. It is thrown when building the SSO HTTP client, so every SSO operation fails until config is fixed.

Solutions

  1. Open config/passbolt.php (or app.php) and set passbolt.security.sso.sslCafile to a string filesystem path to a PEM CA bundle, e.g. '/etc/ssl/certs/ca-certificates.crt'.
  2. If you don't need a custom CA, remove the sslCafile key entirely so resolveVerify() returns true (default system verification).
  3. Confirm sslVerify is a boolean true/false and matches your intent (false disables verification entirely).
  4. Validate config at deploy time with a quick Configure::read() dump to catch type issues before runtime.

Example fix

// before (config/passbolt.php)
'security' => ['sso' => ['sslVerify' => true, 'sslCafile' => true]],
// after
'security' => ['sso' => ['sslVerify' => true, 'sslCafile' => '/etc/ssl/certs/ca-certificates.crt']],
Defensive patterns

Strategy: validation

Validate before calling

$cafile = Configure::read('passbolt.security.sso.sslCafile');
if (Configure::read('passbolt.security.sso.sslVerify') && $cafile !== null) {
    assert(is_string($cafile), 'sslCafile must be a string path');
    assert(file_exists($cafile), 'sslCafile must point to an existing CA bundle');
}

Type guard

function isValidCafile(mixed $cafile): bool {
    return is_string($cafile) && $cafile !== '' && is_file($cafile) && is_readable($cafile);
}

Try / catch

try {
    $client = SsoHttpClientFactory::create();
} catch (\Cake\Http\Exception\BadRequestException $e) {
    $this->log('Bad SSO SSL config: ' . $e->getMessage());
    // abort SSO flow and prompt admin to fix passbolt.security.sso.sslCafile
}

Prevention

When it happens

Trigger: resolveVerify() is invoked from create(); passbolt.security.sso.sslVerify is enabled AND passbolt.security.sso.sslCafile is set to something that is not a string (e.g. true, an array from bad config merge, or a numeric value in config/passbolt.php).

Common situations: Admins setting 'sslCafile' => true expecting 'use CA verification' instead of a path; config files importing the wrong variable type; environment variable interpolation producing non-strings; leftovers from copy-pasted config snippets.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/96a010a1a18254dd. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/Sso/src/Utility/Http/SsoHttpClientFactory.php:70

     * Resolve the Guzzle `verify` option from the SSO SSL configuration.
     *
     * @see https://docs.guzzlephp.org/en/stable/request-options.html#verify
     * @return string|bool `true` for default verification, `false` to disable, or a CA file path.
     * @throws \Cake\Http\Exception\BadRequestException When a custom CA file is configured but invalid.
     */
    private static function resolveVerify(): bool|string
    {
        $sslVerify = (bool)Configure::read(self::CONFIG_SSL_VERIFY, true);
        $sslCafile = Configure::read(self::CONFIG_SSL_CAFILE);

        if ($sslVerify && $sslCafile === null) {
            return true;
        }
        if (!$sslVerify) {
            return false;
        }
        if (!is_string($sslCafile)) {
            throw new BadRequestException(__('Invalid value provided in `passbolt.security.sso.sslCafile` config'));
        }
        if (!file_exists($sslCafile)) {
            throw new BadRequestException(__('Provided root CA file does not exist'));
        }

        return $sslCafile;
    }
}

View on GitHub (pinned to 31c1bbc10f)