Dirty Cert: Cisco Smart Software Manager's Silently Patched RCE A security researcher found a post-auth remote code execution vulnerability in Cisco Smart Software Manager (CSSM) that was silently patched in Cisco's 10-202608 upgrade, uploaded on 10 Aug 2026. The flaw, in the nginx certificate upload path, allowed command injection through TLS certificates because the nginx_configurator's valid_key and valid_cert functions passed certificate and key input to childProcess.execSync running openssl. The researcher said their newly built AI bug hunting harness found the vulnerability within 1 hour. Dirty Cert: Cisco Smart Software Manager's Silently Patched RCE Table of Contents Introduction Back in early August 2026, I was 0-day bug hunting in Cisco Smart Software Manager CSSM . This was where I came across a post-auth RCE vulnerability. This vulnerability, located in the nginx certificate upload, involved command injection via TLS certificates. Unfortunately, a week before I finished the report, the vulnerability was silently patched in their 10-202608 upgrade uploaded on 10 Aug 2026. This short blog will detail the exploit, along with how it got patched. Backstory CSSM is a licensing and account manager for multiple Cisco products such as their edge devices and networking software. It is distributed as an installable OS, running many microservices accessible via an nginx reverse proxy. I was testing out my newly built AI bug hunting harness, which managed to find this vulnerability within 1 hour The Sink that Never Should’ve Been Found within their nginx configurator, in /frontend/usr/share/nginx/nginx configurator/main.js , are these two very interesting functions. function valid key key { try { childProcess.execSync echo "${key}" | openssl rsa /dev/null , { stdio: "inherit", } ; return true; } catch e { log Invalid key: ${e} ; return false; } } function valid cert cert { try { childProcess.execSync echo "${cert}" | openssl x509 /dev/null , { stdio: "inherit", } ; return true; } catch e { log Invalid cert: ${e} ; return false; } } Cisco uses the openssl command to check for invalid certs and RSA keys. Using childProcess.execSync to do so is very risky, but very good for vulnerability researchers like me It just so happens that these functions are called when I upload new certificates for nginx, so all we need is one malformed certificate to achieve command injection. Tracing through the code With our target sink, we now begin tracing all the processing and functions our certificate payload goes through before reaching it. Validator’s Validation Starting with the endpoint /backend/settings/csr/upload to upload our certs, we pass through the nginx reverse proxy to the backend service where we encounter a check under /backend/usr/src/app/validators/admin/certs/csr/upload validator.rb python def validate record private key = CsrPrivateKey.first record.errors.add :base, I18n.t 'browser certs.cert not valid' && return unless private key.present? record.errors.add :base, I18n.t 'browser certs.invalid csr cert' && return unless valid cert? record, private key record.errors.add :base, I18n.t 'browser certs.invalid signature algorithm' && return if algorithm rejected? record.certificate if record.intermediate certificate.present? record.errors.add :base, I18n.t 'browser certs.invalid intermediate cert' && return unless valid intermediate cert? record record.errors.add :base, I18n.t 'browser certs.invalid intermediate cert signature algorithm' if algorithm rejected? record.intermediate certificate end rescue record.errors.add :base,I18n.t 'browser certs.invalid file type' end def valid cert? record, csr private key ui cert = OpenSSL::X509::Certificate.new record.certificate decrypted key = EncryptionService.decrypt csr private key.key data csr rsa private key = OpenSSL::PKey::RSA.new decrypted key CertService.rsa keys eql? ui cert.public key, csr rsa private key end def valid intermediate cert? record user cert = OpenSSL::X509::Certificate.new record.certificate intermediate cert = OpenSSL::X509::Certificate.new record.intermediate certificate user cert.issuer == intermediate cert.subject rescue record.errors.add :base,I18n.t 'browser certs.invalid intermediate cert' end These functions check for: 1. Has the server made a Certificate Signing Request CSR ? 2. Does the new certificate match the CSR? 3. Did the intermediate cert sign the new certificate? 4. Are the certificates signed using the allowed algorithms? 5. Do the certificates all follow the format under OpenSSL::X509::Certificate? No. 1, we simply generate a CSR using the /backend/settings/csr/generate endpoint. No. 2 and 3, we become the root CA and sign the CSR. No. 4 is a non-factor, since the default openssl algorithm is allowlisted. This last check, due to parsing of the request via OpenSSL::X509::Certificate.new record.certificate , is also not foolproof The library follows RFC 7468 “Textual Encodings of PKIX, PKCS, and CMS Structures” , and it states the following: Explanatory Text Many tools are known to emit explanatory text before the BEGIN and after the END lines for PKIX certificates, more than any other type. If emitted, such text SHOULD be related to the certificate, such as providing a textual representation of key data elements in the certificate. By using explanatory text, we can add our command injection before the -----BEGIN CERTIFICATE----- header Something akin to: $