[{"data":1,"prerenderedAt":292},["ShallowReactive",2],{"writing-what-tls-actually-protects":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"updated":10,"tags":11,"draft":6,"body":15,"_type":286,"_id":287,"_source":288,"_file":289,"_stem":290,"_extension":291},"/writing/what-tls-actually-protects","writing",false,"","What TLS actually protects, and what it doesn't","The padlock means less than people assume. What TLS guarantees, what it never covered, and the misconfigurations that quietly remove those guarantees.","2026-06-23",[12,13,14],"tls","cryptography","secure-design",{"type":16,"children":17,"toc":277},"root",[18,26,33,38,49,59,69,74,80,90,100,110,120,130,136,171,181,191,209,234,240,245,251,256,261,266,272],{"type":19,"tag":20,"props":21,"children":22},"element","p",{},[23],{"type":24,"value":25},"text","TLS is the control people are most confident about and least precise about. \"The site is HTTPS, so it's secure\" compresses three specific guarantees and a long list of non-guarantees into one word, and the gap between them is where the interesting failures sit.",{"type":19,"tag":27,"props":28,"children":30},"h2",{"id":29},"the-three-guarantees",[31],{"type":24,"value":32},"The three guarantees",{"type":19,"tag":20,"props":34,"children":35},{},[36],{"type":24,"value":37},"A correctly negotiated TLS connection gives you:",{"type":19,"tag":20,"props":39,"children":40},{},[41,47],{"type":19,"tag":42,"props":43,"children":44},"strong",{},[45],{"type":24,"value":46},"Confidentiality.",{"type":24,"value":48}," Someone on the network path cannot read the contents of the connection.",{"type":19,"tag":20,"props":50,"children":51},{},[52,57],{"type":19,"tag":42,"props":53,"children":54},{},[55],{"type":24,"value":56},"Integrity.",{"type":24,"value":58}," They cannot modify it undetected. This is worth stating separately, because it is the property that stops an ISP or a hostile access point injecting content into a page.",{"type":19,"tag":20,"props":60,"children":61},{},[62,67],{"type":19,"tag":42,"props":63,"children":64},{},[65],{"type":24,"value":66},"Server authentication.",{"type":24,"value":68}," You are talking to a server that holds the private key for a certificate covering the hostname you asked for, signed by a CA your client trusts.",{"type":19,"tag":20,"props":70,"children":71},{},[72],{"type":24,"value":73},"That is the whole list. Everything else people expect from the padlock is somewhere else in the stack.",{"type":19,"tag":27,"props":75,"children":77},{"id":76},"what-it-does-not-give-you",[78],{"type":24,"value":79},"What it does not give you",{"type":19,"tag":20,"props":81,"children":82},{},[83,88],{"type":19,"tag":42,"props":84,"children":85},{},[86],{"type":24,"value":87},"It does not mean the site is trustworthy.",{"type":24,"value":89}," A certificate attests to hostname control, nothing more. A phishing page gets a valid certificate in about a minute, because issuing one is automated and free. The padlock has never meant \"this business is legitimate\", and reading it that way is exactly the confusion phishing relies on.",{"type":19,"tag":20,"props":91,"children":92},{},[93,98],{"type":19,"tag":42,"props":94,"children":95},{},[96],{"type":24,"value":97},"It does not protect data at rest.",{"type":24,"value":99}," The connection is encrypted. What the server writes to its database, its logs, or an S3 bucket afterwards is a separate problem — and logging a request body over TLS into plaintext application logs is a very ordinary way to leak credentials.",{"type":19,"tag":20,"props":101,"children":102},{},[103,108],{"type":19,"tag":42,"props":104,"children":105},{},[106],{"type":24,"value":107},"It does not protect against application bugs.",{"type":24,"value":109}," XSS, SQL injection, broken access control, and IDOR all work perfectly over TLS. The channel is secure; the thing at the end of it is what you actually asked to be attacked.",{"type":19,"tag":20,"props":111,"children":112},{},[113,118],{"type":19,"tag":42,"props":114,"children":115},{},[116],{"type":24,"value":117},"It does not hide who you are talking to.",{"type":24,"value":119}," The destination IP is visible. DNS lookups are visible unless you are using DoH or DoT. Historically the SNI field leaked the hostname in the clear during the handshake — Encrypted Client Hello addresses this, but deployment is far from universal, so assume the hostname is observable.",{"type":19,"tag":20,"props":121,"children":122},{},[123,128],{"type":19,"tag":42,"props":124,"children":125},{},[126],{"type":24,"value":127},"It does not authenticate the client.",{"type":24,"value":129}," By default only the server proves identity. Mutual TLS exists and is worth using for service-to-service traffic, but it is not what happens when a browser visits your site.",{"type":19,"tag":27,"props":131,"children":133},{"id":132},"the-parts-that-break-in-practice",[134],{"type":24,"value":135},"The parts that break in practice",{"type":19,"tag":20,"props":137,"children":138},{},[139,144,146,153,155,161,163,169],{"type":19,"tag":42,"props":140,"children":141},{},[142],{"type":24,"value":143},"Certificate validation turned off.",{"type":24,"value":145}," Almost every language makes this a one-liner: ",{"type":19,"tag":147,"props":148,"children":150},"code",{"className":149},[],[151],{"type":24,"value":152},"verify=False",{"type":24,"value":154},", ",{"type":19,"tag":147,"props":156,"children":158},{"className":157},[],[159],{"type":24,"value":160},"rejectUnauthorized: false",{"type":24,"value":162},", a trust-all ",{"type":19,"tag":147,"props":164,"children":166},{"className":165},[],[167],{"type":24,"value":168},"TrustManager",{"type":24,"value":170},". It usually gets added to unblock a self-signed certificate in staging and then ships. Without validation you keep the encryption and lose server authentication entirely, which means you are encrypting a conversation with an attacker just as happily as with your server. Grep your codebase for these; you will find more than you expect.",{"type":19,"tag":20,"props":172,"children":173},{},[174,179],{"type":19,"tag":42,"props":175,"children":176},{},[177],{"type":24,"value":178},"Hostname verification skipped.",{"type":24,"value":180}," A subtler variant. The chain is verified but nobody checks the certificate actually covers the host being contacted. Any valid certificate from any trusted CA then works for any host.",{"type":19,"tag":20,"props":182,"children":183},{},[184,189],{"type":19,"tag":42,"props":185,"children":186},{},[187],{"type":24,"value":188},"TLS terminated at the edge, plaintext behind it.",{"type":24,"value":190}," Extremely common, and defensible only if you genuinely trust every hop inside the perimeter. In a shared VPC or a multi-tenant cluster that assumption is doing a lot of unexamined work. If the traffic carries anything sensitive, terminate at the edge and re-encrypt inward.",{"type":19,"tag":20,"props":192,"children":193},{},[194,199,201,207],{"type":19,"tag":42,"props":195,"children":196},{},[197],{"type":24,"value":198},"Mixed content.",{"type":24,"value":200}," One ",{"type":19,"tag":147,"props":202,"children":204},{"className":203},[],[205],{"type":24,"value":206},"http://",{"type":24,"value":208}," script tag on an HTTPS page reintroduces the injection path you paid for TLS to close. Browsers block active mixed content now, which converts a security hole into a broken feature — better, but you still have to fix it.",{"type":19,"tag":20,"props":210,"children":211},{},[212,217,219,225,227,232],{"type":19,"tag":42,"props":213,"children":214},{},[215],{"type":24,"value":216},"No HSTS.",{"type":24,"value":218}," Without ",{"type":19,"tag":147,"props":220,"children":222},{"className":221},[],[223],{"type":24,"value":224},"Strict-Transport-Security",{"type":24,"value":226},", a user's first request to ",{"type":19,"tag":147,"props":228,"children":230},{"className":229},[],[231],{"type":24,"value":206},{"type":24,"value":233}," is still cleartext and still strippable. HSTS tells the browser never to try plaintext for your domain again.",{"type":19,"tag":27,"props":235,"children":237},{"id":236},"certificates-expire-and-that-is-the-outage",[238],{"type":24,"value":239},"Certificates expire, and that is the outage",{"type":19,"tag":20,"props":241,"children":242},{},[243],{"type":24,"value":244},"The single most likely TLS incident is not an attack. It is a certificate quietly reaching its expiry date on a Saturday. Automate renewal, and monitor the expiry date independently of the thing that renews it — a renewal job that has been failing silently for six weeks is the standard version of this story.",{"type":19,"tag":27,"props":246,"children":248},{"id":247},"version-and-cipher-hygiene",[249],{"type":24,"value":250},"Version and cipher hygiene",{"type":19,"tag":20,"props":252,"children":253},{},[254],{"type":24,"value":255},"TLS 1.2 and 1.3 only. SSL 2.0 and 3.0 have been broken for years; the name \"SSL\" survives mostly in habit and in library names. TLS 1.0 and 1.1 are deprecated and fail PCI requirements.",{"type":19,"tag":20,"props":257,"children":258},{},[259],{"type":24,"value":260},"TLS 1.3 is a real improvement rather than an increment: it removes the legacy key-exchange and cipher options that made misconfiguration easy, cuts the handshake to one round trip, and makes forward secrecy mandatory. Forward secrecy is the property that matters most in the long run — it means recording traffic today and stealing the private key later does not retroactively decrypt what was captured.",{"type":19,"tag":20,"props":262,"children":263},{},[264],{"type":24,"value":265},"One caveat worth knowing: TLS 1.3's 0-RTT resumption trades a round trip for replay exposure. Do not enable it for non-idempotent requests.",{"type":19,"tag":27,"props":267,"children":269},{"id":268},"the-useful-framing",[270],{"type":24,"value":271},"The useful framing",{"type":19,"tag":20,"props":273,"children":274},{},[275],{"type":24,"value":276},"TLS secures a pipe. It says nothing about what is at either end of it, or what happens to the data once it arrives. Treat it as one control among several — the one that makes network position stop being an attack, so you can concentrate on the attacks that do not need it.",{"title":7,"searchDepth":278,"depth":278,"links":279},2,[280,281,282,283,284,285],{"id":29,"depth":278,"text":32},{"id":76,"depth":278,"text":79},{"id":132,"depth":278,"text":135},{"id":236,"depth":278,"text":239},{"id":247,"depth":278,"text":250},{"id":268,"depth":278,"text":271},"markdown","content:writing:what-tls-actually-protects.md","content","writing/what-tls-actually-protects.md","writing/what-tls-actually-protects","md",1785577357135]