TL;DR: The client builds a chain from the server's leaf through intermediates to a root in its trust store, then checks every link: signature, validity dates, that each signer is a CA (basic constraints), key usage, and that the leaf's Subject Alternative Name matches the requested host. Where required, it also checks revocation and Certificate Transparency proofs. In practice things fail through disabled verification, missing hostname checks, expired certificates, overly broad trust stores, and revocation checks that fail open.
How to approach it
List the checks in order so the interviewer hears a complete procedure, then spend most of the time on failures, ideally ones you have seen. Tie failures to impact: which attacker each one enables.
A strong answer
Each arrow is a signature check; each box has its own rules.
Leaf
api.example.com
Intermediate
CA:TRUE, issues leaves
Root
in the trust store
Checks at each certificate
Leaf rules
- SAN matches the requested host
- EKU allows server authentication
- Valid now; CT proof where required
Intermediate rules
- Basic constraints CA:TRUE, path length
- Name constraints and key usage respected
- Not revoked, not expired
Root rules
- Present in the client's own trust store
- Not distrusted for this purpose
How validation fails in real code
Almost never a broken signature; almost always a skipped check
The procedure.
- Build the chain. Leaf (sent by server) to intermediates (sent by server) to a root (already trusted by the client).
- Verify signatures at each link with the issuer's public key.
- Check validity periods for every certificate.
- Check basic constraints: every certificate that signed another must be marked as a CA, within path-length limits.
- Check key usage: the leaf is allowed for server authentication.
- Match the name: the requested host matches a SAN entry (wildcards cover one label only).
- Check revocation and CT where policy requires: CRLs or OCSP, and signed certificate timestamps for public certificates.
What goes wrong.
| Failure | Cause | Impact |
|---|---|---|
| Verification disabled | verify=False, "trust all" managers, InsecureSkipVerify added to get past an error | Any active attacker can intercept and modify traffic |
| No hostname check | Hand-written validation that checks the chain but not the name | Any valid certificate for any domain impersonates yours |
| Basic constraints ignored | Old or custom validators | A leaf certificate used to sign other certificates is accepted |
| Expired certificates | Manual renewal | Outages, and pressure to disable validation "temporarily" |
| Overly broad trust | Corporate or test roots added to production trust stores | Whoever holds that root can impersonate anything to those clients |
| Revocation fails open | OCSP unreachable, client accepts anyway | Revoked certificates keep working for an attacker who blocks the check |
The practical defences. Use the platform's validator and never disable it; pin to a specific internal CA (not a leaf) for service-to-service calls; automate issuance and renewal (ACME); monitor Certificate Transparency logs for your domains; prefer short-lived certificates, which the industry is moving toward (the CA/Browser Forum approved a phased reduction to 47-day maximum lifetimes by 2029, checked November 2026).
AI context. Agent frameworks, notebooks and internal tool servers are common places to find verify=False. An agent that calls a tool server without verification can be fed forged tool responses by anyone positioned on the network, which is an injection channel as well as a confidentiality problem.
Name matching, in code. The hostname check is small enough to read in full. This sketch follows the RFC 6125 rules most clients apply: a wildcard only as the whole left-most label, matching exactly one label, never a bare public suffix.
def matches(pattern: str, host: str) -> bool:
"""Hostname check in the style of RFC 6125: a wildcard only as the whole
left-most label, matching exactly one label, never a public suffix alone."""
p, h = pattern.lower().rstrip("."), host.lower().rstrip(".")
if "*" not in p:
return p == h
p_labels, h_labels = p.split("."), h.split(".")
if p_labels[0] != "*" or "*" in ".".join(p_labels[1:]):
return False # partial or non-left-most wildcards are rejected
if len(p_labels) < 3:
return False # "*.com" style patterns are never accepted
return len(h_labels) == len(p_labels) and h_labels[1:] == p_labels[1:]
def check(sans: list[str], host: str) -> str:
return "ok" if any(matches(s, host) for s in sans) else "name mismatch"
sans = ["api.example.com", "*.cdn.example.com"]
print(check(sans, "api.example.com")) # => ok
print(check(sans, "img.cdn.example.com")) # => ok
print(check(sans, "a.b.cdn.example.com")) # => name mismatch
print(check(sans, "example.com")) # => name mismatch
print(check(["*.com"], "evil.com")) # => name mismatch
What interviewers probe next
- "Why is revocation so unreliable?" CRLs are large and stale, OCSP adds latency and privacy leakage, and clients soft-fail; shorter lifetimes limit the damage instead.
- "Should you pin certificates?" Pin to a CA or public key you control for internal clients if you can manage rotation; leaf pinning in public apps causes outages when certificates rotate.
- "How do you find disabled verification in a large codebase?" Static analysis rules for the known flags and APIs, plus tests that connect through an intercepting proxy and expect failure.
What if?
What if · interview follow-ups
Hold your answer as the constraints change
Your service's HTTP client is configured with verify=True and a custom CA bundle, and a colleague asks what that actually checks.
Start here
How does the client build a chain?
Where do intermediates come from?
From the server's leaf certificate through intermediates to a root in its trust store. Servers should send intermediates; the root comes from the client's store, here the custom bundle.
Carry it forwardLeaf to intermediates to a trusted root.
Weak answerExpecting the server to send the root.
Constraint changes
What is checked on each link?
What makes an intermediate allowed to sign?
Signature, validity dates, that each signer is a CA (basic constraints), key usage, and that the leaf's Subject Alternative Name matches the requested host. Where required, revocation and Certificate Transparency proofs too.
Carry it forwardSignatures, dates, CA constraints, usage and name.
Weak answerThinking only signatures are checked.
Constraint changes
What does the custom CA bundle change?
Which roots does the client trust now?
It replaces the default trust store, so the client trusts exactly the roots in the bundle. If it includes too much, such as a broad corporate root, more servers can impersonate the API; if too little, valid servers fail.
Carry it forwardThe bundle defines who can be trusted.
Weak answerAdding roots to silence errors.
Constraint changes
How does validation usually fail in practice?
Where might verification be disabled?
Disabled verification left in from debugging, hostname checks turned off, trusting any certificate from a broad root, and libraries used incorrectly. Check for verify=False or equivalent anywhere in the code.
Carry it forwardMost failures are configuration, not cryptography.
Weak answerAssuming the default library settings are used everywhere.
Constraint changes
What would make the connection stronger?
What would stop someone disabling checks during an outage?
For internal APIs, a dedicated internal CA with a narrow bundle, mutual TLS, short-lived certificates and possibly pinning to the internal CA. Monitor expiry so failures do not tempt people to disable verification.
Carry it forwardNarrow trust and automated renewal.
Weak answerPinning leaf certificates without a rotation plan.
Now defend it
How would you answer the colleague?
verify=True builds a chain from leaf through intermediates to a root in the custom bundle and checks signatures, dates, CA constraints, key usage and the hostname; the bundle decides who is trusted, so keep it narrow, search for disabled verification, and consider mutual TLS with short-lived internal certificates.
How it's scored
Weak: Says the client "checks the certificate is signed" and stops.
Hire: Lists chain building, signatures, dates and hostname, and names disabled verification as a common failure.
Strong Hire: Covers basic constraints, revocation behaviour, CT monitoring and lifetime trends, and gives concrete detection and prevention practices.
Common mistakes
- Matching the host against the Common Name instead of SANs.
- Pinning leaf certificates in clients that cannot be updated quickly.
- Treating a "temporary" disabled check as harmless.
- Assuming internal networks do not need validated TLS.