GitHub Packages · MIT · Node ≥ 18

tls-sentinel

Check TLS endpoints for expiring or untrusted certificates, hostname mismatches, missing intermediates, weak keys and signatures, TLS 1.0/1.1, weak ciphers and missing TLS 1.3.

TLS endpoint checker: certificate expiry, hostname mismatch, untrusted or incomplete chains, self-signed certs, weak keys and signatures, TLS 1.0/1.1 and weak ciphers, missing TLS 1.3, long-lived certs. Uses Node's TLS stack, no OpenSSL binary needed. CLI, library and GitHub Action. Zero deps.

  1. 1 Point the @mrlouiswright scope at GitHub Packages in .npmrc

    @mrlouiswright:registry=https://npm.pkg.github.com
  2. 2 Install

    npm i -D @mrlouiswright/tls-sentinel
Installing from GitHub Packages needs a token

Published to GitHub Packages, not npmjs.com. GitHub Packages needs a GitHub token with read:packages to install, even for public packages: add //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} to .npmrc or run npm login --registry=https://npm.pkg.github.com.

~/project — zsh
$ npx tls-sentinel expired.badssl.comtls-sentinel — 1 target(s) expired.badssl.com:443  protocol: TLSv1.2  cipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256  subject: OU=Domain Control Validated, OU=PositiveSSL Wildcard, CN=*.badssl.com  issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Domain Validation Secure Server CA  validTo: 2015-04-12T23:59:59.000Z  daysLeft: -4203  key: rsa 2048  sigAlg: sha256WithRSA  san: DNS:*.badssl.com, DNS:badssl.com  protocols: TLSv1.2... 1 critical, 2 low, 1 info✖ Failing (fail-on: high).
Real output from running tls-sentinel locally on a test fixture.

Why it exists

tls-sentinel connects to each “host[:port]”, inspects the certificate chain the server sends, and probes which protocol versions and cipher families it accepts. It uses Node's own TLS stack, so there is no openssl binary or external service involved, and it only performs handshakes (no HTTP request is sent), so it works for any TLS service: HTTPS, SMTPS, IMAPS, LDAPS, databases. CLI, library and GitHub Action. Node.js 18+, zero runtime dependencies.

Features

Certificate

expired, not yet valid, expiring within --critical-days (default 14, high) or --warn-days (default 30, medium), host name not covered, self-signed, chain not trusted, intermediates missing, RSA < 2048 / EC < 256 bits, SHA-1/MD5 signatures, lifetimes over 398 days, no OCSP stapling.

Protocols and ciphers

accepts TLS 1.0 or 1.1, no TLS 1.3, accepts 3DES/RC4/NULL/EXPORT/anonymous suites, accepts static-RSA key exchange (no forward secrecy), negotiates CBC on TLS 1.2.

cert-expired

Certificate has expired (default: critical)

cert-not-yet-valid

Certificate is not valid yet (default: critical)

hostname-mismatch

Certificate does not cover the host name (default: critical)

untrusted-chain

Chain does not lead to a trusted root (default: critical)

self-signed

Self-signed certificate (default: critical)

incomplete-chain

Server does not send the intermediate certificates (default: high)

Usage

# Example

 npx tls-sentinel example.com www.example.com:443 api.example.com:8443

# Example

 npx tls-sentinel internal.corp:636 --ca corp-root.pem --quick --warn-days 45

# Example

 npx tls-sentinel https://example.com --format sarif > tls.sarif

CI / GitHub Action

permissions:
  contents: read
  security-events: write   # only for the SARIF upload
steps:
  - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
    with: { persist-credentials: false }
  - uses: MrLouisWright/tls-sentinel@v1
    with:
      targets: 'example.com'
      fail-on: high
      sarif: tls-sentinel.sarif
  - uses: github/codeql-action/upload-sarif@v3
    if: always()
    with: { sarif_file: tls-sentinel.sarif }

Options & flags

FlagDescription
--warn-days <n>Medium finding when the certificate expires within n days (default 30)
--critical-days <n>High finding within n days (default 14)
--quickOne handshake only: skip protocol and cipher probes
--servername <name>SNI / expected name (default: the target host)
--ca <file>Extra trusted CA bundle (PEM), e.g. for internal PKI
--timeout <ms>Per-handshake timeout (default 10000)
--concurrency <n>Targets checked in parallel (default 4)
Policy and output
-c, --config <file>JSON config (default .tls-sentinel.json if present)
-f, --format <fmt>text (default) | json | sarif | markdown
--json/--sarif/--markdown <file>Also write that format to a file
--fail-on <sev>critical | high | medium | low | info | none (default high)
--list-rulesPrint rules and default severities
--no-colorDisable colours

Full reference, config file format and API in the README.

Support this project

Support open-source security tools

I build free, open-source tools that help developers ship safer websites. Every coffee helps keep them maintained, documented and free for everyone.

Buy me a coffee (opens Stripe in a new tab)

Secure checkout by Stripe

Portrait of Louis Wright

About the author

Louis Wright

Cyber security researcher and software engineer based in the UK.

More tools by Louis Wright

58 tools

Sentinels security scanners & CI gates · 19