Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Ssl Certificate Laravel Package

spatie/ssl-certificate

A PHP package from Spatie that makes it easy to query SSL certificate properties. Fetch a certificate from a hostname, file, or string, then check validity, expiration dates, issuer, and key details.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

spatie/ssl-certificate is a focused, framework-agnostic value-object library, not a Laravel package in the traditional sense: no service provider, no config file, no facade registration. It depends only on nesbot/carbon and spatie/macroable, both already present in most Laravel codebases. Architecturally it occupies a narrow seam — "given a hostname, file, or DER/PEM string, return a typed certificate object" — which makes it easy to wrap behind our own CertificateInspector interface and swap out later. That is the right shape for us: it should be an implementation detail behind a domain port, never called directly from controllers or Blade views.

Its capabilities are metadata introspection, not validation: isValid(), isExpired(), isValidUntil(), daysUntilExpirationDate(), getDomains(), getAdditionalDomains(), getIssuer(), getSubjectOrganization(), getFingerprintSha256(), getPublicKeyAlgorithm()/Size(), getSignatureAlgorithm(), isSelfSigned(), usesSha1Hash(), getSerialNumber(), plus toArray()/createFromArray() for cache-friendly round-tripping.

Integration feasibility

Low friction. composer require spatie/ssl-certificate, PHP 8+ only (v2.x line), MIT licensed, actively released with a documented changelog back to 1.3.x. The fluent downloader (download()->usingPort()->fromIpAddress()->withSocketContextOptions()->withVerifyPeer()->withVerifyPeerName()->forHost()) covers the awkward cases we actually hit: non-443 ports, pinning a check to a specific A/AAAA record before DNS cutover, IPv6 targets, and custom socket context for SNI or proxy egress. createFromFile() now handles DER as of 2.4.0, which matters if we ingest certificates from an internal CA or an asset inventory rather than the network.

Technical risk

The dominant risk is semantic, not technical: the README explicitly states the package does not check whether a certificate is signed by a trusted authority. isValid() means "now is between notBefore and notAfter, and the hostname matches the SANs" — it does not mean "this certificate is trustworthy." Any code path that treats a true from this library as a security clearance is a defect. Trust decisions must stay with openssl/cURL/Guzzle with peer verification enabled; this package is for reporting, expiry alerting, drift detection, and inventory.

Secondary risks: synchronous TLS handshakes are blocking network I/O with a caller-supplied timeout, so an unreachable host stalls the calling process; wildcard semantics have had real bugs (2.6.10 corrected wildcards incorrectly matching the root domain), so hostname-matching results should be treated as advisory; there are no OCSP/CRL or revocation checks; and "0 dependents" reported by the source data is a weak adoption signal that argues for a thin internal wrapper rather than deep coupling.

Key questions

  • Is the trust-validation gap acceptable for the intended use case, or does a reviewer assume isValid() implies a verified chain?
  • Do we need revocation checking (OCSP/CRL) or intermediate-chain inspection? If yes, this package is insufficient alone.
  • Can production hosts make outbound TCP 443 to arbitrary external hosts, or must checks route through an egress proxy?
  • Does the 2026-06-05 release date correspond to a real, pinnable tag in our registry mirror, or is it a feed artifact?
  • What is our minimum PHP version across all apps that would consume this — are any still on 7.x, which v2.x drops?
  • Do we need IDN/punycode hostnames, and is that handled before or after it reaches the library?

Integration Approach

Stack fit

Near-perfect for a Laravel estate. It slots naturally into three places: (1) a scheduled php artisan command that sweeps a domains table nightly and writes expiry/issuer/fingerprint into a certificate_checks table; (2) an on-demand admin panel action to inspect a tenant's custom domain during onboarding or support triage; (3) a health-check endpoint or dashboard widget for our own infrastructure endpoints. Because toArray()/createFromArray() exist, we can persist the parsed certificate snapshot and diff it release-over-release to detect unexpected issuer or key-size changes — that is where the real product value sits, not in a single isExpired() call.

Migration path

Greenfield — there is nothing to migrate away from. The only "migration" is behavioural: teams currently shelling out to openssl s_client in ad-hoc scripts or copy-pasting expiry dates into a spreadsheet should be redirected to the internal service. Introduce a single CertificateInspector contract in our codebase with one inspect(string $host, int $port = 443): CertificateSnapshot method, implement it with this package, and register the binding in a service provider. Everything else in the application depends on the contract, not on Spatie\SslCertificate\SslCertificate.

Compatibility

PHP 8.0+ required; verify against our matrix. nesbot/carbon is already a Laravel transitive dependency, so no version conflict expected. No Laravel version constraint is imposed, which is good — but it also means no framework integration is provided, so scheduling, queueing, caching, and notification are all ours to wire. Pin the major version (^2.6) and let patch/minor float; the changelog shows a disciplined semver history with no breaking changes inside 2.x.

Sequencing

  1. Spike (1–2 days): wrap in the CertificateInspector contract; validate against a fixture set of known-good, expired, self-signed, wildcard, and multi-SAN certificates plus badssl.com-style targets. Confirm DER-file ingestion and IPv6 paths.
  2. Internal tooling first: an artisan command + table + Slack/mail expiry alert at 30/14/7 days. No user-facing surface, low blast radius, immediate operational value.
  3. Queue the fan-out: move per-host checks onto a queued job with a concurrency cap and per-host timeout, so a slow or dead host can never block a request or a scheduler tick.
  4. Expose read-only: surface results in the admin panel and an API endpoint reading from the persisted snapshot table, never triggering a live handshake inline.
  5. Only then consider any customer-facing product surface (e.g. domain health for tenants), and only after confirming the trust-validation caveat is understood by whoever writes the copy.

Operational Impact

Maintenance

Very low. MIT license, single maintainer organisation (Spatie) with a long, consistent release cadence and a readable changelog. The API surface we depend on is small and stable, which caps our exposure to upstream churn. The real maintenance cost is not the dependency — it's the monitoring product we build on top of it: alert thresholds, the domain inventory, and the snapshot retention policy. Budget accordingly.

Support

Spatie supports this as open source with no SLA; the "postcardware" framing in the README is a fair signal of expected support posture. Escalation path for a bug is a GitHub issue, and realistically a fork or a local patch if we hit an edge case (wildcard matching is the historically fragile area — see 1.3.2 and 2.6.10). Because it's MIT, forking is a legitimate fallback; keep the wrapper thin so a fork swap is a one-file change.

Scaling

The library does not scale itself — it does one blocking TLS handshake per call. At a few hundred domains nightly, that is trivially fine. At tens of thousands, the constraint is outbound connection concurrency and DNS resolution, not CPU. Design for queue workers with bounded concurrency (say 20–50 in flight), a 5–10 second connect timeout, and exponential backoff on transient failures. Persist snapshots so dashboards and alerts read from the database, never from live handshakes. Cache per host for at least an hour to absorb repeated dashboard loads.

Failure modes

  • CouldNotDownloadCertificate — DNS failure, refused connection, closed port, or TLS handshake rejected. Note that with verifyCertificate = false (third argument to createForHostName) you can retrieve expired or otherwise invalid certificates, which is exactly what you want for alerting: an expired cert must still be reportable, not silently a connection error. This distinction must be deliberate in the implementation.
  • InvalidUrl / InvalidIpAddress — thrown on malformed input; validate at the boundary and treat as a validation error, not a system failure.
  • Timeouts — the silent killer. Must be explicit and short; a hung handshake should surface as an "unknown/unreachable" state distinct from "expired."
  • False assurance — the most dangerous mode. A green dashboard driven solely by isValid() will report healthy for a self-signed or wrong-CA certificate. Pair every trust-sensitive display with a genuine verification check, and label isValid() results as "expiry and hostname match," not "secure."

Ramp-up

Effectively zero for a PHP developer — the README is complete and example-driven, and the entire API is discoverable in an afternoon. The learning curve is not the library; it's the TLS domain literacy required to interpret what it returns. Invest half a day in making sure the team understands the difference between "this certificate is currently within its validity window and names this host" and "this certificate is trusted by this client," because that misunderstanding is the only way this integration causes real harm.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log