npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

certnotify

v0.3.2

Published

Open-source internet exposure scanner — SSL/TLS, DNS, DNSSEC, email security (SPF/DKIM/DMARC), HTTP security headers, open ports, DNSBL reputation, uptime, DNS-hijack monitoring, defacement detection, WHOIS-privacy monitoring, mixed-content scanning, an

Readme

certnotify

Open-source internet exposure scanner, from the command line. No account, no API key, no phoning home.

npx certnotify scan example.com
CERTNOTIFY SECURITY SCAN

Target: example.com
Scanned: 2026-08-29T12:00:00.000Z

Security Score: 84/100

✓ SSL Certificate — TLSv1.3 (grade A+), expires in 62d
✓ Domain registration — registrar Example Registrar, expires in 210d
✓ DNSSEC — signed-valid
✓ Email security (SPF/DKIM/DMARC) — grade B (72/100)
✓ Security headers — grade B (70/100)
✓ Port scan — no unexpected open ports (checked 15)
✓ Blacklist check — clean (0/7 lists)
✓ Uptime — Online (up), 210ms (Good)

What it checks

| Check | What it does | |---|---| | ssl | TLS handshake, certificate validity/expiry, issuer, TLS version and grade | | whois | Domain registration status and expiry, via public RDAP (not the legacy WHOIS protocol) | | dns | A / AAAA / MX / TXT / NS / CNAME / SOA / PTR (reverse) records | | dnssec | DNSSEC signing and validation status, via DNS-over-HTTPS | | email | SPF, DKIM (common selectors), and DMARC posture and grade | | headers | HTTP security headers (HSTS, CSP, X-Frame-Options, and 7 more), graded not just presence-checked | | ports | TCP-connect probe against 15 well-known ports (databases, admin panels, dev servers) | | blacklist | Cross-references your domain's IP against 7 public DNSBL feeds | | uptime | HTTPS check with HTTP fallback — status, response time, performance rating, redirects |

Every check uses only Node's built-in tls/dns/net modules or free, keyless public services (RDAP registries, Cloudflare DNS-over-HTTPS, public DNSBL zones) — no paid API keys, no telemetry, no phone-home.

Stateful checks

The 9 checks above are stateless — run them anywhere, anytime, no history required. The 5 checks below compare against a local baseline from your previous run, so they need somewhere to remember what "normal" looked like. That baseline is a plain JSON file per target under ~/.certnotify/state by default (override with --state-dir <path>) — no database, no account, nothing leaves your machine.

| Command | What it does | |---|---| | dns-monitor | Diffs A/AAAA/MX/NS/TXT/CNAME records against the last run — flags possible DNS hijacking. Changes to A/AAAA/NS/MX are marked critical. | | defacement | Fingerprints the homepage (title, meta description, headings, visible text) and flags any change since the last run. | | whois-privacy | Detects when WHOIS privacy protection gets disabled, exposing the registrant's real contact details. | | mixed-content | Scans the homepage and a handful of linked/sitemap pages for HTTP resources embedded in HTTPS pages, tracking first-seen time and occurrence count. | | subdomains | Combines real Certificate Transparency log data (every certificate ever issued for the domain) with a common-prefix DNS probe, and tracks which subdomains are new since the last run. |

certnotify dns-monitor example.com     # baseline on first run, diff on every run after
certnotify defacement example.com
certnotify whois-privacy example.com
certnotify mixed-content example.com
certnotify subdomains example.com --limit 30

All five accept --state-dir <path> and --json.

Install

npm install -g certnotify
certnotify scan example.com

Or run it once without installing:

npx certnotify scan example.com

Docker

docker build -t certnotify .
docker run --rm certnotify scan example.com

The stateful checks keep their baseline in ~/.certnotify/state, which does not survive a container exiting. Mount a volume to make them useful across runs:

docker run --rm -v certnotify-state:/home/certnotify/.certnotify \
  certnotify dns-monitor example.com

GitHub Actions

- uses: siddhantmallah/certnotify-community@main
  with:
    target: example.com
    fail-on: 70          # fail the job below 70/100; omit to only record

| Input | Default | | |---|---|---| | target | — | Domain or host to scan (required) | | checks | all | Comma-separated subset, e.g. ssl,headers,email | | fail-on | never | Fail the job when the composite score is below this | | version | latest | Which certnotify release to run | | json-path | certnotify-report.json | Where the JSON report is written | | summary | true | Write the readable report to the job summary |

Outputs score and json-path. The scan runs once and the job summary is rendered from that same result rather than scanning the target twice.

Usage

certnotify scan <target>                 # run every check
certnotify scan <target> --only ssl,dns,email
certnotify scan <target> --json          # machine-readable output, e.g. for CI
certnotify ssl <target>                  # run a single check directly, prints raw JSON

Every check that connects to a user-supplied host refuses to scan private, loopback, link-local, or cloud-metadata addresses by default (SSRF protection). Pass --allow-private to override this for legitimate local-network testing.

As a library

import { scan } from 'certnotify';

const report = await scan('example.com', { checks: ['ssl', 'headers'] });

Each individual scanner (checkSSL, checkWhois, checkDns, checkDnssec, checkEmail, checkHeaders, checkPorts, checkBlacklist, checkUptime) is also exported directly, as are the 5 stateful checks (checkDnsChanges, checkDefacement, checkWhoisPrivacy, checkMixedContent, discoverSubdomains) and the readState/writeState helpers they're built on:

import { checkDnsChanges, readState } from 'certnotify';

const result = await checkDnsChanges('example.com', { stateDir: './baselines' });
if (result.suspicious) {
  // a critical record type (A/AAAA/NS/MX) changed since the last run
}

Relationship to CertNotify Cloud

This CLI is the open-source core of CertNotify — continuous monitoring, historical trends, team alerting, and a hosted dashboard live at certnotify.com. This package will always contain a genuine, complete security engine on its own; the hosted product is about continuous monitoring and correlation across many assets over time, not gatekeeping the scanners themselves.

License

GNU AGPL v3.0 or later. If you run a modified version of this project as a network service, you must make your modified source available to users of that service — this is what keeps the project from being quietly forked into a closed competing product.

Contributing

CONTRIBUTING.md covers the setup, how to add a check, and why there are no mocks in the test suite. Security issues go to [email protected] — see SECURITY.md.

A false positive or false negative is the most useful bug report this project can get; there is an issue template for exactly that.

Changelog

  • 0.3.0 — email now detects multiple SPF records. A domain publishing more than one v=spf1 record is a permanent error under RFC 7208 §4.5: receivers do not pick one, they fail SPF for the domain outright. This checker previously took the first match and reported such a domain as healthy — the worst way an SPF check can be wrong, since the owner's mail is failing authentication and every first-match tool tells them it is fine. spf now carries records, multipleRecords and error, the version tag is matched case-insensitively per §3.2, and spf.valid is false when duplicates make the policy unevaluable. Also: --json output now includes the composite score (it was only ever printed in the human-readable report, which made threshold-gating a CI build unnecessarily awkward), plus a Dockerfile and a GitHub Action.
  • 0.2.0 — 5 new stateful checks that compare against a local baseline: dns-monitor (DNS-hijack detection), defacement (homepage content-fingerprint monitoring), whois-privacy (registrant privacy-protection monitoring), mixed-content (HTTP-in-HTTPS resource scanning), and subdomains (Certificate Transparency log + brute-force discovery). Baselines live in ~/.certnotify/state by default, overridable with --state-dir. All additive, no breaking changes.
  • 0.1.1 — checkDnssec now returns rcode: { dnskey, ds } (the raw DoH response codes); checkHeaders now returns rawHeaders (every header the server sent, not just the 10 checked) so a consumer can inspect anything else — e.g. Cache-Control — without a second request. Both are additive, no breaking changes.
  • 0.1.0 — Initial release: 9 checks (ssl, whois, dns, dnssec, email, headers, ports, blacklist, uptime), CLI + library.

Status

v0.3.0 — public. Live on npm and GitHub. 14 real checks (9 stateless + 5 stateful), a vitest suite (unit tests for security-critical/pure logic like the SSRF guard, SPF parsing and the stateful checks' parsing logic, plus live integration tests against real domains — no mocks anywhere), distributed as a CLI, a library, a Docker image and a GitHub Action.

The CI workflow is set to manual dispatch rather than running on push: the repo owner's GitHub account is billing-locked (unrelated to this project and not being resolved), so every triggered run fails in two seconds without a runner ever starting. Rather than paint the history red with failures that say nothing about the code, the workflow is parked and npm run verify — the same typecheck, build and test steps — is the gate. Flipping the trigger back is a two-line change, documented in the workflow file.

See ROADMAP-OPENSOURCE.md for what's planned next (new domains — secrets scanning, IaC/container scanning, SAST, DAST — built by orchestrating established open-source tools rather than reinventing them).

Development

npm install
npm run typecheck   # tsc --noEmit across src/ and test/
npm run build       # tsup — emits CJS + ESM + .d.ts to dist/
npm test            # vitest — unit tests + live integration tests against real domains