Challenge 3: Spot the Security Mistake — Possible Solution ==================================================================== WHAT'S WRONG: createInsecure() means every call on that channel travels as PLAINTEXT — no encryption at all. Working "fine" in local testing is exactly the trap this chapter's gotcha describes: an insecure channel is genuinely convenient for local development (no certificates to generate or manage), which makes it easy to leave in place and simply forget to swap for createSsl() before the code actually reaches production. In production, this means: anyone positioned to observe network traffic between the client and this service — a compromised intermediate host, anyone on a shared or compromised network segment — can read every single call in full, including any bearer token attached via metadata (Chapter 5/6/7's auth pattern). An attacker who captures that plaintext token can then reuse it to impersonate the legitimate caller entirely, since the token itself was never protected by any transport-level encryption. This is the exact same class of mistake the site has flagged repeatedly in other contexts — an unencrypted database connection (dbsec1-6), a MongoDB TLS setting that encrypts without verifying identity (mongodb2-6) — the specific mechanism differs, but the root mistake is identical: treating "it works" as equivalent to "it's secure," when encryption was never actually enabled at all. THE FIX: switch to grpc.credentials.createSsl() (or the mTLS variant from this chapter, if applicable) before any deployment outside local development — and ideally, catch this class of mistake with an automated check in CI rather than relying on someone remembering to change it manually.