certspotter

package module
v0.24.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 23, 2026 License: MPL-2.0 Imports: 14 Imported by: 24

README

Cert Spotter - Certificate Transparency Monitor - Open Source Edition

Cert Spotter is a Certificate Transparency log monitor from SSLMate that alerts you when an SSL/TLS certificate is issued for one of your domains. Cert Spotter is easier to use than other open source CT monitors, since it does not require a database. It's also more robust, since it uses a special certificate parser that ensures it won't miss certificates.

Cert Spotter is available as a hosted service by SSLMate that also provides monitoring for expiring and incorrectly-installed certificates, Slack notifications, and a Web dashboard for tracking all of your certificates. Visit https://sslmate.com/certspotter to sign up.

You can use Cert Spotter to detect:

  • Certificates issued to attackers who have compromised your DNS and are redirecting your visitors to their malicious site.
  • Certificates issued to attackers who have taken over an abandoned sub-domain in order to serve malware under your name.
  • Certificates issued to attackers who have compromised a certificate authority and want to impersonate your site.
  • Certificates issued in violation of your corporate policy or outside of your centralized certificate procurement process.

Quickstart

The following instructions require you to have Go version 1.21 or higher installed.

  1. Install the certspotter command using the go command:

    go install software.sslmate.com/src/certspotter/cmd/certspotter@latest
    
  2. Create a watch list file $HOME/.certspotter/watchlist containing the DNS names you want to monitor, one per line. To monitor an entire domain tree (including the domain itself and all sub-domains) prefix the domain name with a dot (e.g. .example.com). To monitor a single DNS name only, do not prefix the name with a dot.

  3. Place one or more email addresses in the $HOME/.certspotter/email_recipients file (one per line), and/or place one or more executable scripts in the $HOME/.certspotter/hooks.d directory. certspotter will email the listed addresses (requires your system to have a working sendmail command) and execute the provided scripts when it detects a certificate for a domain on your watch list.

  4. Configure your system to run certspotter as a daemon. You may want to specify the -start_at_end command line option to tell certspotter to start monitoring new logs at the end instead of the beginning. This saves significant bandwidth, but you won't be notified about certificates which were logged before you started using certspotter.

Documentation

Authorizing Known Certificates to Prevent False Alarms

You can use the certspotter-authorize command to tell certspotter about legitimate certificates issued by your certificate authority. certspotter won't notify you when it discovers an authorized certificate (or its corresponding precertificate) in Certificate Transparency logs.

To install certspotter-authorize, run:

go install software.sslmate.com/src/certspotter/cmd/certspotter-authorize@latest

To authorize a certificate, run:

certspotter-authorize /path/to/cert.pem

For more details, see the certspotter-authorize(8) man page.

What certificates are detected by Cert Spotter?

In the default configuration, any certificate that is logged to a Certificate Transparency log listed as Qualified, Usable, or ReadOnly in the Google Chrome or Apple log lists will be detected by Cert Spotter. By default, Chrome, Safari, Firefox, and Edge only accept certificates that are logged to at least one such log (Firefox and Edge use the Chrome log list), so any certificate that works in these browsers will be detected by Cert Spotter.

Cert Spotter monitors both traditional RFC6962 logs and modern static-ct-api logs.

Security

Cert Spotter assumes an adversarial model in which an attacker produces a certificate that is accepted by at least some clients but goes undetected because of an encoding error that prevents CT monitors from understanding it. To defend against this attack, Cert Spotter uses a special certificate parser that keeps the certificate unparsed except for the identifiers. If one of the identifiers matches a domain on your watchlist, you will be notified, even if other parts of the certificate are unparsable.

Cert Spotter takes special precautions to ensure identifiers are parsed correctly, and implements defenses against identifier-based attacks. For instance, if a DNS identifier contains a null byte, Cert Spotter interprets it as two identifiers: the complete identifier, and the identifier formed by truncating at the first null byte. For example, a certificate for example.org\0.example.com will alert the owners of both example.org and example.com. This defends against null prefix attacks.

SSLMate continuously monitors CT logs to make sure every certificate's identifiers can be successfully parsed, and will release updates to Cert Spotter as necessary to fix parsing failures.

Cert Spotter understands wildcard DNS names, and will alert you if a wildcard certificate might match an identifier on your watchlist. For example, a watchlist entry for sub.example.com would match certificates for *.example.com.

Cert Spotter is not just a log monitor, but also a log auditor which checks that the log is obeying its append-only property. A future release of Cert Spotter will support gossiping with other log monitors to ensure the log is presenting a single view.

Testing

Every day at around 12:05 UTC, a certificate is issued and logged to CT for the DNS name DAY-OF-WEEK.test.certspotter.org. You can add one or more of these DNS names (or .test.certspotter.org) to your watch list to get confirmation that Cert Spotter is working.

DNS Name Issuer Key Type
monday.test.certspotter.org Sectigo RSA
tuesday.test.certspotter.org Let's Encrypt ECDSA
wednesday.test.certspotter.org Google RSA
thursday.test.certspotter.org Sectigo ECDSA
friday.test.certspotter.org Let's Encrypt RSA
saturday.test.certspotter.org Google ECDSA
sunday.test.certspotter.org Let's Encrypt ECDSA

Copyright © 2016-2026 Opsmate, Inc.

Licensed under the Mozilla Public License Version 2.0.

Documentation

Index

Constants

View Source
const UnparsableDNSLabelPlaceholder = "<unparsable>"

Variables

This section is empty.

Functions

func MarshalRDNSequence

func MarshalRDNSequence(rdns RDNSequence) ([]byte, error)

func MatchesWildcard

func MatchesWildcard(dnsName string, pattern string) bool

Types

type AttributeTypeAndValue

type AttributeTypeAndValue struct {
	Type  asn1.ObjectIdentifier
	Value asn1.RawValue
}

type CertInfo

type CertInfo struct {
	TBS *TBSCertificate

	Subject                RDNSequence
	SubjectParseError      error
	Issuer                 RDNSequence
	IssuerParseError       error
	SANs                   []SubjectAltName
	SANsParseError         error
	SerialNumber           *big.Int
	SerialNumberParseError error
	Validity               *CertValidity
	ValidityParseError     error
	IsCA                   *bool
	IsCAParseError         error
	IsPreCert              bool
}

func MakeCertInfoFromRawCert

func MakeCertInfoFromRawCert(certBytes []byte) (*CertInfo, error)

func MakeCertInfoFromRawTBS

func MakeCertInfoFromRawTBS(tbsBytes []byte) (*CertInfo, error)

func MakeCertInfoFromTBS

func MakeCertInfoFromTBS(tbs *TBSCertificate) *CertInfo

func (*CertInfo) ParseIdentifiers

func (cert *CertInfo) ParseIdentifiers() (*Identifiers, error)

type CertValidity

type CertValidity struct {
	NotBefore time.Time
	NotAfter  time.Time
}

type Certificate

type Certificate struct {
	Raw asn1.RawContent

	TBSCertificate     asn1.RawValue
	SignatureAlgorithm asn1.RawValue
	SignatureValue     asn1.RawValue
}

func ParseCertificate

func ParseCertificate(certBytes []byte) (*Certificate, error)

func (*Certificate) GetRawTBSCertificate

func (cert *Certificate) GetRawTBSCertificate() []byte

func (*Certificate) ParseSignatureAlgorithm

func (cert *Certificate) ParseSignatureAlgorithm() (*pkix.AlgorithmIdentifier, error)

func (*Certificate) ParseSignatureValue

func (cert *Certificate) ParseSignatureValue() ([]byte, error)

func (*Certificate) ParseTBSCertificate

func (cert *Certificate) ParseTBSCertificate() (*TBSCertificate, error)

type Extension

type Extension struct {
	Id       asn1.ObjectIdentifier
	Critical bool `asn1:"optional"`
	Value    []byte
}

type Identifiers

type Identifiers struct {
	DNSNames []string // stored as ASCII, with IDNs in Punycode
	IPAddrs  []net.IP
}

func NewIdentifiers

func NewIdentifiers() *Identifiers

func (*Identifiers) AddCN

func (ids *Identifiers) AddCN(value string)

func (*Identifiers) AddDnsSAN

func (ids *Identifiers) AddDnsSAN(value []byte)

func (*Identifiers) AddIPAddress

func (ids *Identifiers) AddIPAddress(value net.IP)

type PrecertInfo

type PrecertInfo struct {
	SameIssuer bool   // The pre-certificate was issued from the same CA as the final certificate
	Issuer     []byte // The pre-certificate's issuer, if different from the final certificate
	AKI        []byte // The pre-certificate's AKI, if present and different from the final certificate
}

func ValidatePrecert

func ValidatePrecert(precertBytes []byte, tbsBytes []byte) (*PrecertInfo, error)

type RDNSequence

type RDNSequence []RelativeDistinguishedNameSET

func CanonicalizeRDNSequence

func CanonicalizeRDNSequence(oldSequence RDNSequence) (RDNSequence, error)

func ParseRDNSequence

func ParseRDNSequence(rdnsBytes []byte) (RDNSequence, error)

func (RDNSequence) ParseCNs

func (rdns RDNSequence) ParseCNs() ([]string, error)

func (RDNSequence) String

func (rdns RDNSequence) String() string

type RelativeDistinguishedNameSET

type RelativeDistinguishedNameSET []AttributeTypeAndValue

type SubjectAltName

type SubjectAltName struct {
	Type  int
	Value []byte
}

func ParseSANExtension added in v0.17.0

func ParseSANExtension(sans []SubjectAltName, value []byte) ([]SubjectAltName, error)

func (SubjectAltName) String

func (san SubjectAltName) String() string

type TBSCertificate

type TBSCertificate struct {
	Raw asn1.RawContent

	Version            int `asn1:"optional,explicit,default:1,tag:0"`
	SerialNumber       asn1.RawValue
	SignatureAlgorithm asn1.RawValue
	Issuer             asn1.RawValue
	Validity           asn1.RawValue
	Subject            asn1.RawValue
	PublicKey          asn1.RawValue
	UniqueId           asn1.BitString `asn1:"optional,tag:1"`
	SubjectUniqueId    asn1.BitString `asn1:"optional,tag:2"`
	Extensions         []Extension    `asn1:"optional,explicit,tag:3"`
}

func ParseTBSCertificate

func ParseTBSCertificate(tbsBytes []byte) (*TBSCertificate, error)

func ReconstructPrecertTBS

func ReconstructPrecertTBS(tbs *TBSCertificate) (*TBSCertificate, error)

func (*TBSCertificate) GetExtension

func (tbs *TBSCertificate) GetExtension(id asn1.ObjectIdentifier) []Extension

func (*TBSCertificate) GetRawIssuer

func (tbs *TBSCertificate) GetRawIssuer() []byte

func (*TBSCertificate) GetRawPublicKey

func (tbs *TBSCertificate) GetRawPublicKey() []byte

func (*TBSCertificate) GetRawSubject

func (tbs *TBSCertificate) GetRawSubject() []byte

func (*TBSCertificate) ParseBasicConstraints

func (tbs *TBSCertificate) ParseBasicConstraints() (*bool, error)

func (*TBSCertificate) ParseIssuer

func (tbs *TBSCertificate) ParseIssuer() (RDNSequence, error)

func (*TBSCertificate) ParseSerialNumber

func (tbs *TBSCertificate) ParseSerialNumber() (*big.Int, error)

func (*TBSCertificate) ParseSubject

func (tbs *TBSCertificate) ParseSubject() (RDNSequence, error)

func (*TBSCertificate) ParseSubjectAltNames

func (tbs *TBSCertificate) ParseSubjectAltNames() ([]SubjectAltName, error)

func (*TBSCertificate) ParseSubjectCommonNames

func (tbs *TBSCertificate) ParseSubjectCommonNames() ([]string, error)

func (*TBSCertificate) ParseValidity

func (tbs *TBSCertificate) ParseValidity() (*CertValidity, error)

Directories

Path Synopsis
cmd
certspotter command
Package ctclient implements a client for monitoring RFC6962 and static-ct-api Certificate Transparency logs
Package ctclient implements a client for monitoring RFC6962 and static-ct-api Certificate Transparency logs
mozilla
Package mozilla contains a parser for Mozilla's CTKnownLogs.h file
Package mozilla contains a parser for Mozilla's CTKnownLogs.h file

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL