SyntaxStudy
Sign Up
Web Security Mixed Content, Certificate Pinning, and HTTPS Best Practices
Web Security Beginner 1 min read

Mixed Content, Certificate Pinning, and HTTPS Best Practices

Mixed content occurs when an HTTPS page loads resources — scripts, stylesheets, images, iframes — over HTTP. Active mixed content (scripts and stylesheets) is blocked by all modern browsers because it lets a network attacker inject malicious code into an otherwise secure page. Passive mixed content (images, audio, video) is displayed with a warning but still poses privacy and integrity risks. Fix mixed content by auditing all resource URLs with the browser console or tools like `mixed-content-scan` and ensuring every asset is served over HTTPS. HTTP Public Key Pinning (HPKP) was a mechanism that let servers specify which public keys browsers should accept for their certificates, defending against rogue CAs. It was deprecated and removed from browsers because misconfiguration could permanently lock users out of a site. The recommended replacement for high-security scenarios is Certificate Transparency monitoring combined with CAA (Certification Authority Authorisation) DNS records, which restrict which CAs can issue certificates for your domain. A complete HTTPS deployment checklist includes: redirect all HTTP traffic to HTTPS at the load balancer level, use TLS 1.2+ and disable older protocol versions, configure only strong cipher suites, rotate certificates automatically using ACME (Let's Encrypt), set HSTS with a long max-age, add HSTS preloading, and publish CAA DNS records. Regularly audit your configuration with tools like SSL Labs' SSL Test to catch regressions.
Example
# nginx configuration: secure HTTPS with best practices

server {
    listen 80 default_server;
    server_name example.com www.example.com;
    # Redirect all HTTP to HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # Modern TLS configuration (Mozilla SSL Config Generator — modern profile)
    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;
    ssl_prefer_server_ciphers off;

    # Session tickets & OCSP stapling
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_stapling on;
    ssl_stapling_verify on;

    # HSTS (preload-eligible)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # CAA DNS record (set in your DNS provider):
    # example.com. CAA 0 issue "letsencrypt.org"
    # example.com. CAA 0 issuewild ";"

    location / {
        proxy_pass http://app:8000;
    }
}