Dev.to Security 🔐 Cybersecurity 👁 0 📖 5 min read

The TLS Layer Under app.onepassapps.com: Two Hosts, Two Certificates, and the Cipher We Actually Negotiate

The TLS Layer Under app.onepassapps.com: Two Hosts, Two Certificates, and the Cipher We Actually Negotiate Full disclosure: I work on OnePassApps, so this is a measurement of our own site rather than a third party's.

The TLS Layer Under app.onepassapps.com: Two Hosts, Two Certificates, and the Cipher We Actually Negotiate

Full disclosure: I work on OnePassApps, so this is a measurement of our own site rather than a third party's.

We have written a lot about what app.onepassapps.com sends back over HTTP: the response headers, the Content-Security-Policy, the manifest, the chunk files, the fonts. This post covers the layer underneath all of that - the handshake that happens before a single response header is written, and the two certificates that make it work.

Everything below was measured from outside the browser on 5 November 2026, with plain openssl s_client and curl against the live hosts. No signed-in session, no cookies, no JavaScript.

Two hosts, two different certificates

Our app and API run on different hostnames, and they do not present the same certificate.

Host Certificate subject Names in the SAN Valid from Valid until
app.onepassapps.com CN=app.onepassapps.com DNS:app.onepassapps.com Oct 28 2026 20:47:40 UTC Jan 26 2027 21:47:38 UTC
api.onepassapps.com CN=onepassapps.com DNS:onepassapps.com, DNS:*.onepassapps.com Sep 18 2026 15:05:10 UTC Dec 17 2026 16:04:55 UTC

Two details in that table are worth pausing on.

First, the app host's certificate covers exactly one name: app.onepassapps.com. It is not a wildcard. The API host's certificate is the apex name plus a *.onepassapps.com wildcard, so a single API certificate could have served the app host too - it does not.

Second, both certificates are short-lived. The app certificate was issued on 28 October 2026 and expires on 26 January 2027: a 90-day lifetime, with 82 days left on the day I measured. The API certificate was issued on 18 September 2026 and expires on 17 December 2026: also 90 days, with 42 left. This is the normal rotation Google Trust Services issues behind Cloudflare, and it means the fingerprint below is a snapshot, not a permanent identity.

Both certificates are signed by C=US, O=Google Trust Services, CN=WE1, use ECDSA (ecdsa-with-SHA256) with a 256-bit public key, and are marked CA:FALSE with the key usage Digital Signature and the extended key usage TLS Web Server Authentication - the correct, minimal set for a leaf server certificate.

The app certificate's SHA-256 fingerprint on 5 November 2026:

B1:D3:C7:B8:0C:3C:23:DE:C8:A8:11:0A:CA:C3:BD:5E:AE:5B:05:39:60:4E:B3:F6:55:80:85:0F:79:30:5A:D7

Chains verify cleanly against the system trust store (Verify return code: 0 (ok)), and both hosts resolve to the same two IPv4 addresses, 104.21.69.121 and 172.67.208.4, plus a Cloudflare IPv6 address each.

The cipher we actually negotiate

Forcing a protocol version and reading what came back:

Forced version Result
TLS 1.3 New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
TLS 1.2 New, TLSv1.2, Cipher is ECDHE-ECDSA-CHACHA20-POLY1305
TLS 1.1 New, (NONE), Cipher is (NONE) - refused
TLS 1.0 New, (NONE), Cipher is (NONE) - refused

TLS 1.0 and TLS 1.1 are refused outright: the handshake never gets to a cipher. TLS 1.3 picks TLS_AES_256_GCM_SHA384, and the 1.2 fallback is ECDHE-ECDSA-CHACHA20-POLY1305 - ECDHE key exchange with a ChaCha20-Poly1305 cipher, so a 1.2 connection still gets forward secrecy.

One ALPN choice, and HTTP/3 advertised but not proven

Both hosts negotiate the same way when the client offers both protocols:

ALPN protocol: h2

ALPN protocol: h2 on app.onepassapps.com, and the same line on api.onepassapps.com. curl confirms the end result at the HTTP layer: http_version=2 and ssl_verify_result=0 for the app host, http_version=2 for the API host.

The response headers also carry alt-svc: h3=":443"; ma=86400 on both hosts, which advertises HTTP/3 over QUIC on the same port. I want to be precise about what that does and does not prove: the advertisement is real, but I could not measure an actual HTTP/3 response - the curl on this machine is built without HTTP/3 support (the installed libcurl version does not support this), so h3 remains advertised and untested from here. Everything else in this post is a value I read back from a live connection.

HSTS for 180 days, and no preload

The same header appears on the home page, on a Studio route and on the API:

strict-transport-security: max-age=15552000; includeSubDomains

15552000 seconds is exactly 180 days. includeSubDomains extends it to every other subdomain of onepassapps.com, so the API host's certificate and its HTTPS-only rule are covered by the same policy even before you visit the API yourself.

One thing that header does not mean: we are not on the HSTS preload list. The hstspreload.org status API answers "status": "unknown" with an empty preloadedDomain for app.onepassapps.com. A browser enforces our policy once it has seen the header, but it does not enforce it on a first visit.

HTTP redirects, and a hostname that does not resolve

The plain-HTTP entry points all land on HTTPS with a single hop:

Request Result
http://app.onepassapps.com/ 301 to https://app.onepassapps.com/
http://app.onepassapps.com/ followed final URL https://app.onepassapps.com/, 200, 1 redirect
https://onepassapps.com/ 301 to https://app.onepassapps.com/
https://www.onepassapps.com/ no DNS answer - the name does not resolve

So the apex redirects to the app host, and www is not a name we serve at all. Both hosts report server: cloudflare.

What is not there

Two things a site often exposes and ours does not. /.well-known/security.txt answers 404, and so does /humans.txt. There is also no source map to read: the entry bundle /assets/index-CKM47TUG.js (321,856 bytes) contains no sourceMappingURL, and asking for the matching .map file answers 404 with the same 13,953-byte not-found document every other missing URL gets.

None of that is a security win by itself. It just means the public surface is smaller than the file tree suggests: no .map files to fetch, no source to reconstruct from, one certificate per hostname, one hostname that does not resolve, and no plaintext HTTP anywhere except the 301 that sends you to HTTPS.

Why it matters for a tool that claims to keep files in the tab

Our Studios say they process files in the browser instead of uploading them. That claim is about what leaves the tab, and the transport layer is where such a claim would break if it were broken: an upload is an HTTPS request with your file in the body, and it would show up as a request to a host.

So the honest way to read this post is: here is the connection that serves the page, and here is what it negotiates. Whether a given file leaves the tab is a separate question, answered by watching the network while you drop a file into a tool. I have written about that separately.

The short version of the whole layer: one edge certificate per hostname, 90-day lifetimes, TLS 1.3 preferred, TLS 1.0 and 1.1 refused, h2 negotiated, HTTP/3 advertised, HSTS at 180 days with includeSubDomains, no preload, and no plaintext.

Try it yourself at https://app.onepassapps.com?utm_source=devto&utm_medium=blog&utm_campaign=tls-transport-layer&utm_content=home-link - and the app guides are at https://app.onepassapps.com/guides?utm_source=devto&utm_medium=blog&utm_campaign=tls-transport-layer&utm_content=guides-link.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.