Quick Answer
SSL/TLS issues in vibe-coded apps fall into five categories: no HTTPS at all, expired certificates, untrusted certificate authorities, deprecated TLS protocol versions (TLS 1.0/1.1), and missing certificate chain files. Platforms like Vercel and Netlify handle certificates automatically, but custom domains, subdomains, and self-hosted deployments are frequently misconfigured - and AI tools never check for them.
Why SSL Problems Happen in AI-Generated Apps
SSL/TLS configuration sits below the application layer. AI coding tools like Bolt, Lovable, Cursor, and v0 generate code, not infrastructure. When they scaffold a Next.js app and you deploy it to Vercel, certificate management is handled automatically. The problems arise the moment you step outside the golden path: custom domains, staging environments, subdomains, self-hosted Node.js servers, or any backend that isn't a managed platform.
According to the 2024 Sectigo Global Certificate Lifecycle Management Report, certificate-related outages affected 80% of organizations in the past year. For startups and indie developers, the equivalent is a "Your connection is not private" warning that silently destroys conversion rates before the founder notices. The SSL Store's research found that expired certificates account for 35% of all TLS-related incidents - entirely preventable with basic monitoring.
A Veracode analysis of web applications found that TLS misconfiguration issues appear in 38% of scanned web apps, including use of deprecated protocol versions and weak cipher suites that have known vulnerabilities.
The Five SSL/TLS Issues to Check
| Issue | Check ID | Severity | Common Cause in Vibe Apps |
|---|---|---|---|
| No HTTPS / HTTP only | SSL-001 | Critical | Self-hosted Node.js, dev server left in production |
| Expired certificate | SSL-002 | Critical | Let's Encrypt renewal failure, forgotten custom domain |
| Untrusted CA / self-signed | SSL-003 | High | Dev cert left on staging, internal tools deployed publicly |
| Deprecated TLS version (1.0/1.1) | SSL-004 | High | Older VPS, unmanaged Nginx config |
| Incomplete certificate chain | SSL-005 | Medium | Manual cert installation, missing intermediate CA |
HTTPS: Non-Negotiable in 2025
Modern browsers mark HTTP sites as "Not Secure" in the address bar. Google has used HTTPS as a ranking signal since 2014. Browser APIs that vibe-coded apps depend on - Service Workers, clipboard access, geolocation, camera - all require a secure context (HTTPS). Running a production application over plain HTTP in 2025 is not a risk tolerance question; it's a functional limitation.
// ❌ BAD - Express server started without TLS
// server.js - AI-generated, deployed to a bare VPS
import express from 'express';
const app = express();
app.get('/', (req, res) => res.send('Hello world'));
// This starts an HTTP server - no TLS at all.
// Anyone on the same network can read all traffic.
app.listen(3000, () => {
console.log('Server running on port 3000');
});
// ✅ GOOD - Option A: Terminate TLS at a reverse proxy (recommended)
// Use Nginx or Caddy in front of your Node.js server.
// Caddy automatically provisions Let's Encrypt certificates:
// Caddyfile:
// your-domain.com {
// reverse_proxy localhost:3000
// }
// That's the entire config - Caddy handles cert issuance and renewal.
// ✅ GOOD - Option B: Use a managed platform
// Deploy to Vercel, Netlify, Railway, or Render.
// All provision and auto-renew certificates for custom domains.
// Zero configuration required for HTTPS.
Certificate Expiry: The Preventable Outage
Let's Encrypt certificates are valid for 90 days. The short validity window is intentional - it encourages automation. When auto-renewal works, it's invisible. When it fails, your site goes down with a browser warning that looks like a security attack to your users.
Common reasons Let's Encrypt renewal fails on vibe-coded deployments:
- The DNS record was changed (new hosting, domain migration) and the ACME challenge can no longer reach the server
- The certbot cron job or systemd timer was never set up on a self-managed VPS
- Port 80 is firewalled, preventing the HTTP-01 challenge
- The certificate was issued for
www.domain.combut the app now runs ondomain.com(or vice versa)
// ✅ GOOD - Check your certificate expiry from the command line
// Run this to see when your cert expires:
// echo | openssl s_client -servername your-domain.com \
// -connect your-domain.com:443 2>/dev/null \
// | openssl x509 -noout -dates
// Output:
// notBefore=Jan 15 10:23:41 2026 GMT
// notAfter=Apr 15 10:23:41 2026 GMT
// For automated monitoring, set up a cron job or use
// a free service like UptimeRobot (SSL monitoring tab)
// to alert you 30 days before expiry.
TLS Protocol Versions: Deprecating TLS 1.0 and 1.1
TLS 1.0 and 1.1 are deprecated by the IETF (RFC 8996, 2021). Both versions have known vulnerabilities including BEAST, POODLE, and Lucky13 attacks. All major browsers removed support for TLS 1.0 and 1.1 by 2020. Servers still accepting these protocol versions fail security audits and PCI DSS compliance requirements.
If your app is deployed on a modern platform (Vercel, Netlify, Cloudflare), TLS 1.0 and 1.1 are disabled automatically. If you're running Nginx on a VPS - common for self-hosted Supabase, custom backend APIs, or staging servers scaffolded by Cursor - you need to verify your configuration:
// ❌ BAD - Nginx config accepting deprecated TLS versions
// /etc/nginx/sites-available/your-app
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; // TLS 1.0 and 1.1 are vulnerable
// ✅ GOOD - Nginx config with TLS 1.2 and 1.3 only
// /etc/nginx/sites-available/your-app
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# Add HSTS to enforce HTTPS at the browser level
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
Incomplete Certificate Chains
An incomplete certificate chain occurs when your server sends only its end-entity certificate without the intermediate CA certificates needed to establish trust. Some browsers can complete the chain by fetching intermediate certificates from Authority Information Access (AIA) URLs, but many clients - especially mobile apps, API clients, and older browsers - cannot.
This manifests as connections that work in Chrome but fail in curl, mobile apps, or monitoring tools. The fix is to include the full chain (end-entity cert + intermediate CA cert) in your certificate bundle.
How to Audit Your SSL Configuration
Tools like VibeDoctor (vibedoctor.io) automatically scan your app's SSL certificate for expiry, trust chain validity, protocol version support, and HTTPS enforcement - flagging specific issues with check IDs SSL-001 through SSL-005. Free to sign up.
For manual auditing, Qualys SSL Labs (ssllabs.com/ssltest/) provides a comprehensive free SSL/TLS report including protocol support, cipher suites, chain completeness, and an A/F letter grade. For expiry monitoring, UptimeRobot's free plan includes SSL certificate monitoring with configurable alert thresholds.
FAQ
Does Vercel automatically handle SSL for custom domains?
Yes. When you add a custom domain to a Vercel project, Vercel provisions a Let's Encrypt certificate automatically and handles all renewals. HTTPS is enforced by default. The SSL issues that affect Vercel apps are typically on subdomains pointed to non-Vercel infrastructure, or API backends that aren't deployed on Vercel.
What happens when a Let's Encrypt certificate expires?
Browsers show a full-page warning ("Your connection is not private / NET::ERR_CERT_DATE_INVALID"). Most users will leave immediately. API clients will throw SSL errors. Search engines may de-index the site. The fix is to renew the certificate, but you should set up monitoring to catch it 30 days before expiry.
Is a self-signed certificate acceptable for staging environments?
For staging environments accessed only by your own team, self-signed certificates are acceptable if everyone adds a security exception. However, many CI/CD pipelines, automated tests, and API clients reject self-signed certificates by default. Let's Encrypt certificates are free and work for publicly accessible staging subdomains (e.g., staging.yourdomain.com).
How do I redirect HTTP to HTTPS in a Next.js app on Vercel?
Vercel redirects HTTP to HTTPS automatically for all deployments. For custom Next.js servers or Express backends, add a middleware check: if req.headers['x-forwarded-proto'] !== 'https', redirect to the HTTPS equivalent. Behind a load balancer, check the x-forwarded-proto header rather than req.secure, since the TLS termination happens upstream.
What TLS version should my app support?
Support TLS 1.2 and TLS 1.3. Disable TLS 1.0 and 1.1 entirely - they are deprecated and have known vulnerabilities. TLS 1.3 offers improved performance (1-RTT handshake) and stronger security. All modern browsers and clients from the past five years support TLS 1.2 and 1.3, so disabling older versions has negligible compatibility impact.