ssl-inspector
v1.0.0
Published
Inspect SSL/TLS configuration of any HTTPS domain. Generate SPKI pins for React Native SSL pinning.
Maintainers
Readme
SSL Inspector
Inspect SSL/TLS configuration of any HTTPS domain. Extract certificate metadata, generate SPKI pinning hashes, detect Cloudflare, and produce React Native SSL pinning output compatible with @bam.tech/react-native-app-security.
Features
- Certificate Chain Inspection — Full certificate chain with all metadata (subject, issuer, SAN, key usage, fingerprints, etc.)
- SPKI Hash Generation — SHA-256 hashes of SubjectPublicKeyInfo in Base64 and Hex formats
- Cloudflare Detection — Automatically detects Cloudflare Universal SSL vs custom certificates
- React Native Pinning — Generate output for
@bam.tech/react-native-app-security - Pin Comparison — Compare current pins against saved pins to detect rotation
- PEM Export — Export full certificate chain to PEM files
- JSON Output — Machine-readable JSON export
- Expiration Warnings — Color-coded expiration status (green/yellow/red/expired)
- Zero External Dependencies on OpenSSL — Pure Node.js implementation using
node:tlsandnode:crypto
Installation
Install from npm (recommended for public use)
npm install -g ssl-inspectorOr run directly without installing:
npx ssl-inspector example.comInstall locally in your project (development)
# Clone the repository
git clone https://github.com/EricMensah/ssl-inspector.git
cd ssl-inspector
# Install dependencies
npm install
# Build the CLI
npm run build
# Option 1: Run directly
node dist/cli.js example.com
# Option 2: Link globally for CLI access
npm link
ssl-inspector example.com
# Option 3: Add as a project dependency
npm install --save-dev ssl-inspector
npx ssl-inspector example.comCLI Usage
ssl-inspector <hostname> [options]Arguments
| Argument | Description |
|-------------|----------------------------------------------------|
| hostname | Domain or URL to inspect (e.g., api.example.com) |
Options
| Option | Description |
|-------------------|----------------------------------------------------------------|
| --json | Output results as JSON |
| --pins | Display SPKI pinning hashes for all certificates |
| --compare <file>| Compare current pins against a saved pins.json file |
| --bam | Generate React Native output for @bam.tech/react-native-app-security |
| --export <dir> | Export certificate chain as PEM files to a directory |
| -V, --version | Display version number |
| -h, --help | Display help |
Examples
Basic Inspection
ssl-inspector mobile-api.example.comDisplays TLS info, full certificate chain with all metadata, and Cloudflare detection.
JSON Output
ssl-inspector api.example.com --jsonSPKI Pins Only
ssl-inspector api.example.com --pinsCompare Against Saved Pins
Detect if any certificates have rotated:
ssl-inspector api.example.com --compare pins.jsonWhere pins.json contains:
{
"pins": [
"AAAAA...",
"BBBBB..."
]
}React Native Output
ssl-inspector api.example.com --bamOutputs a TypeScript file compatible with @bam.tech/react-native-app-security:
export const sslPins = [
{
hostname: "api.example.com",
publicKeyHashes: [
"AAAAA...",
"BBBBB..."
]
}
];Export PEM Certificates
ssl-inspector api.example.com --export ./certsCreates:
certs/
leaf.pem
intermediate-1.pem
intermediate-2.pem
root.pemReact Native SSL Pinning
Installation
npm install @bam.tech/react-native-app-securityUsage
- Inspect your API domain:
ssl-inspector mobile-api.example.com --bamCopy the generated
sslPinsarray into your React Native project.Configure the security provider:
import { SecurityProvider } from '@bam.tech/react-native-app-security';
import { sslPins } from './sslPins';
<SecurityProvider pins={sslPins}>
<App />
</SecurityProvider>Cloudflare Notes
Detection
SSL Inspector automatically detects Cloudflare by:
- Checking certificate issuer and subject for Cloudflare patterns
- Checking HTTP response headers for
cf-rayandserver: cloudflare
Universal SSL Warning
Cloudflare Universal SSL certificates use hostnames like sni.cloudflaressl.com and are automatically rotated by Cloudflare. These certificates are not suitable for long-term SSL pinning because:
- They may rotate without notice
- The SPKI hash will change on rotation
- Your app will break until you update the pins
Recommendation
If you need SSL pinning behind Cloudflare, install a custom origin certificate (upload your own certificate to Cloudflare) and pin against that. Custom certificates are stable and under your control.
SPKI Explanation
What is SPKI?
SubjectPublicKeyInfo (SPKI) is a data structure in X.509 certificates that contains the public key material. Unlike the full certificate fingerprint (which changes when the certificate is re-issued), the SPKI hash remains stable as long as the same key pair is used.
Why SPKI for Pinning?
The SPKI hash is the recommended value for SSL pinning because:
- It survives certificate re-issuance (same key, new cert)
- It's supported by Android's Network Security Config
- It's used by
@bam.tech/react-native-app-security - It follows the HTTP Public Key Pinning (HPKP) standard
Generated Values
| Value | Format | Use Case |
|----------------------|---------|----------------------------------|
| spkiSHA256Base64 | Base64 | Recommended for pinning |
| spkiSHA256Hex | Hex | Debugging/logging |
| fingerprintSHA256 | Hex | Certificate fingerprint (changes on re-issue) |
PCI DSS Notes
SSL Inspector can assist with PCI DSS compliance requirements:
- Requirement 2.2: Verify strong cryptography is used (TLS 1.2+)
- Requirement 4.1: Ensure certificate validity and proper chain of trust
- Requirement 12.x: Document and monitor certificate configurations
Troubleshooting
"Connection timed out"
The server is not responding on port 443. Check:
- The hostname is correct and resolvable via DNS
- The server is accepting HTTPS connections
- A firewall is not blocking the connection
- A VPN or proxy is not interfering
"TLS handshake failed"
The server rejected the TLS connection. Possible causes:
- The server only supports older TLS versions (1.0/1.1)
- The server requires SNI and it wasn't sent correctly
- The server uses a self-signed certificate that triggers errors
"No certificate received from server"
The TLS connection was established but no certificate was sent. This can happen with:
- Raw TCP connections (non-HTTPS)
- Protocols that negotiate certificates after protocol switch
"DNS lookup failed"
The hostname could not be resolved. Check:
- The hostname is spelled correctly
- DNS servers are reachable
- The domain exists and has DNS records
"Failed to parse certificate"
The certificate uses an unsupported format or is malformed. This is rare with standard HTTPS servers.
Programmatic API
import { connectAndFetch } from 'ssl-inspector/dist/tls.js';
import { parseCertificateChain } from 'ssl-inspector/dist/certificate.js';
import { detectCloudflare } from 'ssl-inspector/dist/cloudflare.js';
const { rawChain, tlsInfo } = await connectAndFetch('example.com');
const chain = parseCertificateChain(rawChain);
const cfInfo = await detectCloudflare(chain, 'example.com');Development
# Install dependencies
npm install
# Build
npm run build
# Dev mode (watch)
npm run dev
# Test
npm test
# Test with watch mode
npm run test:watchProject Structure
ssl-inspector/
├── src/
│ ├── cli.ts — CLI entry point (Commander)
│ ├── tls.ts — TLS connection
│ ├── certificate.ts — Certificate parsing
│ ├── pinning.ts — SPKI hash generation
│ ├── cloudflare.ts — Cloudflare detection
│ ├── compare.ts — Pin comparison
│ ├── export.ts — JSON/PEM/RN export
│ ├── errors.ts — Custom error classes
│ ├── utils.ts — Display formatting
│ └── types.ts — TypeScript interfaces
├── tests/ — Vitest test suite
├── dist/ — Built output
└── README.mdLicense
MIT © Eric Mensah
