What actually stops any Certificate Authority from issuing a certificate for your domain?
The primary technical control is the CAA DNS record (RFC 8659), and its enforcement model is precise in a way operators often miss.
Without CAA, the WebPKI's default is permissive: every publicly-trusted CA may issue for any domain. CAA (Certification Authority Authorization) inverts that default for your zone. A record like example.com. CAA 0 issue "letsencrypt.org" declares that only Let's Encrypt may issue certificates for that name.
The enforcement point is the crux. CAA is checked at issuance time by the CA, not at validation time by the browser. A conforming CA is mandated by the CA/Browser Forum Baseline Requirements to query CAA and refuse issuance if a record forbids it. Browsers do not check CAA — so a CA that ignores the record (or a compromised one) can still issue, and the client won't notice. CAA constrains honest CAs; it is a policy fence, not a cryptographic wall.
The tag set is worth knowing: issue (standard certs), issuewild (wildcards specifically), and iodef (a URL where the CA reports rejected issuance attempts — a free misissuance alarm). CAA also climbs the DNS tree, so a record at the parent applies unless a subdomain overrides it.
Further reading: RFC 8659, RFC 8657 (CAA for ACME account binding); CA/Browser Forum Baseline Requirements §3.2.2.8.
Bottom line: CAA tells honest CAs who may issue, enforced at issuance not validation — set iodef to get alerted whenever someone tries to obtain a cert you didn't authorize.
The primary technical control is the CAA DNS record (RFC 8659), and its enforcement model is precise in a way operators often miss.
Without CAA, the WebPKI's default is permissive: every publicly-trusted CA may issue for any domain. CAA (Certification Authority Authorization) inverts that default for your zone. A record like example.com. CAA 0 issue "letsencrypt.org" declares that only Let's Encrypt may issue certificates for that name.
The enforcement point is the crux. CAA is checked at issuance time by the CA, not at validation time by the browser. A conforming CA is mandated by the CA/Browser Forum Baseline Requirements to query CAA and refuse issuance if a record forbids it. Browsers do not check CAA — so a CA that ignores the record (or a compromised one) can still issue, and the client won't notice. CAA constrains honest CAs; it is a policy fence, not a cryptographic wall.
The tag set is worth knowing: issue (standard certs), issuewild (wildcards specifically), and iodef (a URL where the CA reports rejected issuance attempts — a free misissuance alarm). CAA also climbs the DNS tree, so a record at the parent applies unless a subdomain overrides it.
Further reading: RFC 8659, RFC 8657 (CAA for ACME account binding); CA/Browser Forum Baseline Requirements §3.2.2.8.
Bottom line: CAA tells honest CAs who may issue, enforced at issuance not validation — set iodef to get alerted whenever someone tries to obtain a cert you didn't authorize.
What actually distinguishes the three ACME challenge types, and why does TLS-ALPN-01 exist?
Automatic Certificate Management Environment (ACME, RFC 8555) is the protocol behind Let's Encrypt. It proves you control a domain before issuing a certificate. The three challenges differ in what surface they probe, and the differences are operationally load-bearing.
HTTP-01 proves control of a web server: the CA fetches a token at http://domain/.well-known/acme-challenge/. It is simple but cannot validate wildcards and requires port 80 reachable.
DNS-01 proves control of the zone by placing a TXT record at _acme-challenge.domain. It is the only challenge that issues wildcards (*.domain), and it works without any inbound web traffic — but it demands DNS API automation, and a leaked API key is broader exposure than a single web path.
TLS-ALPN-01 (RFC 8737) is the subtle one. The CA opens a TLS connection on port 443 negotiating the acme-tls/1 protocol via ALPN (Application-Layer Protocol Negotiation, RFC 7301); the server answers with a special self-signed cert carrying the validation token in an extension. Its purpose is specific: validate entirely within the TLS layer, so a reverse proxy or load balancer can terminate ACME without touching the HTTP application or freeing port 80.
Further reading: RFC 8555 §8, RFC 8737, RFC 7301.
Bottom line: HTTP-01 probes a web path, DNS-01 probes the zone (and alone does wildcards), TLS-ALPN-01 probes the TLS layer itself — pick by which surface you can automate safely.
Automatic Certificate Management Environment (ACME, RFC 8555) is the protocol behind Let's Encrypt. It proves you control a domain before issuing a certificate. The three challenges differ in what surface they probe, and the differences are operationally load-bearing.
HTTP-01 proves control of a web server: the CA fetches a token at http://domain/.well-known/acme-challenge/. It is simple but cannot validate wildcards and requires port 80 reachable.
DNS-01 proves control of the zone by placing a TXT record at _acme-challenge.domain. It is the only challenge that issues wildcards (*.domain), and it works without any inbound web traffic — but it demands DNS API automation, and a leaked API key is broader exposure than a single web path.
TLS-ALPN-01 (RFC 8737) is the subtle one. The CA opens a TLS connection on port 443 negotiating the acme-tls/1 protocol via ALPN (Application-Layer Protocol Negotiation, RFC 7301); the server answers with a special self-signed cert carrying the validation token in an extension. Its purpose is specific: validate entirely within the TLS layer, so a reverse proxy or load balancer can terminate ACME without touching the HTTP application or freeing port 80.
Further reading: RFC 8555 §8, RFC 8737, RFC 7301.
Bottom line: HTTP-01 probes a web path, DNS-01 probes the zone (and alone does wildcards), TLS-ALPN-01 probes the TLS layer itself — pick by which surface you can automate safely.
Does forward secrecy protect data you already sent before a key compromise?
The phrase invites a misreading: "forward secrecy means past traffic is safe even if my key leaks — so I'm covered retroactively." The protection is real but its direction is precise, and getting it backwards leads to false comfort. Forward secrecy (PFS), delivered in TLS 1.3 by mandatory ephemeral Diffie-Hellman (ECDHE), means each session derives its symmetric keys from a temporary key pair that is discarded after the handshake. Compromising the server's long-term private key later does not let an attacker decrypt previously recorded sessions, because that long-term key never encrypted the traffic — it only authenticated the handshake.
The boundary people miss: PFS protects past sessions against a future compromise of the long-term key. It does not protect a session whose ephemeral key is captured in memory during its lifetime, nor does it help if the same ephemeral key is reused across sessions (an implementation bug that voids the property). "Harvest now, decrypt later" against TLS 1.3 is also why ephemerality, not certificate strength, is the relevant defense.
— PFS uses per-session ephemeral keys
— It defends past sessions from future long-term-key leaks
— Reused ephemeral keys silently break it
Further reading: RFC 8446, §2 and §7.1.
Bottom line: Forward secrecy protects already-sent data against a later key compromise — provided ephemeral keys are truly per-session and discarded.
—
Про lcp basics подробнее — @CoreVitals101
The phrase invites a misreading: "forward secrecy means past traffic is safe even if my key leaks — so I'm covered retroactively." The protection is real but its direction is precise, and getting it backwards leads to false comfort. Forward secrecy (PFS), delivered in TLS 1.3 by mandatory ephemeral Diffie-Hellman (ECDHE), means each session derives its symmetric keys from a temporary key pair that is discarded after the handshake. Compromising the server's long-term private key later does not let an attacker decrypt previously recorded sessions, because that long-term key never encrypted the traffic — it only authenticated the handshake.
The boundary people miss: PFS protects past sessions against a future compromise of the long-term key. It does not protect a session whose ephemeral key is captured in memory during its lifetime, nor does it help if the same ephemeral key is reused across sessions (an implementation bug that voids the property). "Harvest now, decrypt later" against TLS 1.3 is also why ephemerality, not certificate strength, is the relevant defense.
— PFS uses per-session ephemeral keys
— It defends past sessions from future long-term-key leaks
— Reused ephemeral keys silently break it
Further reading: RFC 8446, §2 and §7.1.
Bottom line: Forward secrecy protects already-sent data against a later key compromise — provided ephemeral keys are truly per-session and discarded.
—
Про lcp basics подробнее — @CoreVitals101
What actually happens when a TLS 1.3 session ticket fails to resume?
TLS (Transport Layer Security) 1.3 offers two resumption paths via PSK (Pre-Shared Key): the standard 1-RTT mode and 0-RTT early data. When a ticket is rejected, the mechanism is not a failure but a fallback, and understanding the branch point matters.
The client sends its PSK identity in the ClientHello extension (RFC 8446, §4.2.11). If the server cannot decrypt the ticket — expired key, rotated STEK (Session Ticket Encryption Key), or unknown identity — it simply omits the pre_shared_key extension from its ServerHello. The client detects the absence and silently transitions to a full handshake, negotiating fresh keys via the key_share extension.
The subtle cost is 0-RTT early data. If the client gambled and sent application data in the first flight, that data is rejected (the server signals via the absence of the early_data extension in EncryptedExtensions). The client MUST be prepared to retransmit it over the freshly negotiated keys. This is why 0-RTT is unsafe for non-idempotent requests — RFC 8446 §2.3 and §8 warn explicitly about replay.
Evidence vs. speculation: the spec mandates the fallback; what varies in practice is how aggressively servers rotate STEKs (often hourly), which is the dominant cause of resumption misses in the wild.
Further reading: RFC 8446 §2.2, §2.3, §4.6.1.
Bottom line: A rejected ticket degrades gracefully to a full handshake; the real hazard is unconfirmed 0-RTT data, which the application layer — not TLS — must be designed to replay safely.
TLS (Transport Layer Security) 1.3 offers two resumption paths via PSK (Pre-Shared Key): the standard 1-RTT mode and 0-RTT early data. When a ticket is rejected, the mechanism is not a failure but a fallback, and understanding the branch point matters.
The client sends its PSK identity in the ClientHello extension (RFC 8446, §4.2.11). If the server cannot decrypt the ticket — expired key, rotated STEK (Session Ticket Encryption Key), or unknown identity — it simply omits the pre_shared_key extension from its ServerHello. The client detects the absence and silently transitions to a full handshake, negotiating fresh keys via the key_share extension.
The subtle cost is 0-RTT early data. If the client gambled and sent application data in the first flight, that data is rejected (the server signals via the absence of the early_data extension in EncryptedExtensions). The client MUST be prepared to retransmit it over the freshly negotiated keys. This is why 0-RTT is unsafe for non-idempotent requests — RFC 8446 §2.3 and §8 warn explicitly about replay.
Evidence vs. speculation: the spec mandates the fallback; what varies in practice is how aggressively servers rotate STEKs (often hourly), which is the dominant cause of resumption misses in the wild.
Further reading: RFC 8446 §2.2, §2.3, §4.6.1.
Bottom line: A rejected ticket degrades gracefully to a full handshake; the real hazard is unconfirmed 0-RTT data, which the application layer — not TLS — must be designed to replay safely.
Why does an OCSP check almost never actually block a revoked certificate?
OCSP (Online Certificate Status Protocol, RFC 6960) lets a client ask a CA's responder: is this certificate still valid? In theory, a revoked certificate is caught here. In practice, the dominant browser policy is soft-fail, and the mechanism quietly collapses.
Soft-fail means: if the OCSP responder is unreachable, slow, or returns an error, the client treats the certificate as valid and proceeds. The reasoning is availability — responders go down, and hard-failing would make sites unreachable. But a network attacker who can present a stolen-and-revoked certificate can also simply block the OCSP request, forcing the soft-fail path. The revocation check becomes security theater against exactly the adversary it was designed to stop.
This is not speculation. Adam Langley's 2012 analysis ("Revocation checking and Chrome's CRL") laid out the soft-fail futility argument, and Chrome subsequently disabled online OCSP for most certificates in favor of CRLSets — a curated, pushed list of high-value revocations. Firefox retains OCSP but with short timeouts and soft-fail.
The partial answer is OCSP stapling (RFC 6066, §8): the server fetches and attaches a signed, time-stamped OCSP response itself, removing the responder round-trip and the privacy leak. With the Must-Staple flag (RFC 7633), a missing staple becomes hard-fail.
Further reading: RFC 6960; RFC 7633; A. Langley, imperialviolet.org (2012).
Bottom line: Plain OCSP soft-fail stops honest mistakes, not active attackers; stapling plus Must-Staple is the only configuration that meaningfully enforces revocation.
OCSP (Online Certificate Status Protocol, RFC 6960) lets a client ask a CA's responder: is this certificate still valid? In theory, a revoked certificate is caught here. In practice, the dominant browser policy is soft-fail, and the mechanism quietly collapses.
Soft-fail means: if the OCSP responder is unreachable, slow, or returns an error, the client treats the certificate as valid and proceeds. The reasoning is availability — responders go down, and hard-failing would make sites unreachable. But a network attacker who can present a stolen-and-revoked certificate can also simply block the OCSP request, forcing the soft-fail path. The revocation check becomes security theater against exactly the adversary it was designed to stop.
This is not speculation. Adam Langley's 2012 analysis ("Revocation checking and Chrome's CRL") laid out the soft-fail futility argument, and Chrome subsequently disabled online OCSP for most certificates in favor of CRLSets — a curated, pushed list of high-value revocations. Firefox retains OCSP but with short timeouts and soft-fail.
The partial answer is OCSP stapling (RFC 6066, §8): the server fetches and attaches a signed, time-stamped OCSP response itself, removing the responder round-trip and the privacy leak. With the Must-Staple flag (RFC 7633), a missing staple becomes hard-fail.
Further reading: RFC 6960; RFC 7633; A. Langley, imperialviolet.org (2012).
Bottom line: Plain OCSP soft-fail stops honest mistakes, not active attackers; stapling plus Must-Staple is the only configuration that meaningfully enforces revocation.
Why does a TLS 1.3 ClientHello often carry a key share for a group the server never picks?
TLS 1.3 collapses the old multi-round negotiation into a single round trip by having the client speculate. In the ClientHello, the client sends two distinct extensions: supported_groups (the curves it is willing to use) and key_share (actual ephemeral public keys, but only for a guessed subset). This is RFC 8446 §4.2.8 and §4.2.7.
The optimistic case: the client guesses X25519, the server agrees, and a full ECDHE (Elliptic Curve Diffie-Hellman Ephemeral) key exchange completes in one round trip. The pessimistic case: the client guessed wrong — it offered only X25519 but the server requires P-256. The server cannot proceed, but it does not abort. Instead it sends a HelloRetryRequest (RFC 8446 §4.1.4) naming the group it wants, and the client resends a ClientHello with a fresh key_share for that group.
The cost is one extra round trip — the handshake degrades from 1-RTT to 2-RTT. This is precisely why clients send a key_share for their most-likely group and merely list the rest: a wider guess wastes a CPU-expensive ephemeral keygen on the common path; a narrower guess risks the retry on the rare path.
Evidence vs. speculation: the post-quantum hybrid X25519MLKEM768 group has shifted these economics, because its key shares are kilobytes, not 32 bytes — making over-guessing measurably expensive again.
Further reading: RFC 8446 §4.1.4, §4.2.7, §4.2.8.
Bottom line: The duplicate-looking key share is a calculated bet to save a round trip; HelloRetryRequest is the graceful, one-RTT-slower fallback when the bet fails.
TLS 1.3 collapses the old multi-round negotiation into a single round trip by having the client speculate. In the ClientHello, the client sends two distinct extensions: supported_groups (the curves it is willing to use) and key_share (actual ephemeral public keys, but only for a guessed subset). This is RFC 8446 §4.2.8 and §4.2.7.
The optimistic case: the client guesses X25519, the server agrees, and a full ECDHE (Elliptic Curve Diffie-Hellman Ephemeral) key exchange completes in one round trip. The pessimistic case: the client guessed wrong — it offered only X25519 but the server requires P-256. The server cannot proceed, but it does not abort. Instead it sends a HelloRetryRequest (RFC 8446 §4.1.4) naming the group it wants, and the client resends a ClientHello with a fresh key_share for that group.
The cost is one extra round trip — the handshake degrades from 1-RTT to 2-RTT. This is precisely why clients send a key_share for their most-likely group and merely list the rest: a wider guess wastes a CPU-expensive ephemeral keygen on the common path; a narrower guess risks the retry on the rare path.
Evidence vs. speculation: the post-quantum hybrid X25519MLKEM768 group has shifted these economics, because its key shares are kilobytes, not 32 bytes — making over-guessing measurably expensive again.
Further reading: RFC 8446 §4.1.4, §4.2.7, §4.2.8.
Bottom line: The duplicate-looking key share is a calculated bet to save a round trip; HelloRetryRequest is the graceful, one-RTT-slower fallback when the bet fails.
Neighbor spotlight: @PingbackClinic. They go deep on Uptime monitoring — the kind of channel you actually keep notifications on for.
What is the one risk nobody mentions about HSTS preloading?
HSTS (HTTP Strict Transport Security, RFC 6797) lets a site command browsers to use only HTTPS for a given duration via the Strict-Transport-Security header. But the header has a bootstrap flaw: the very first visit, before any header is seen, can be intercepted and downgraded. The preload list closes this gap — and introduces a sharper edge.
The preload list is a hardcoded set, compiled into Chromium and inherited by Firefox, Safari, and Edge, of domains that should be HTTPS-only from the first byte, no header required. To qualify, a site must serve the header with max-age of at least 31536000 (one year), the includeSubDomains directive, and the preload token.
Here is the under-discussed risk: removal is slow. Adding a domain is a code change shipped in a browser release; removing it is the same, plus the long tail of users who never update. A domain that preloads includeSubDomains commits every current and future subdomain to HTTPS. If an internal subdomain — a legacy device, an IoT management page, a vendor appliance — cannot serve a valid certificate, it becomes unreachable, and the fix takes browser-release cycles, often months.
Evidence vs. speculation: this is documented at hstspreload.org, which explicitly warns that submission is a long-term, hard-to-reverse commitment.
Further reading: RFC 6797 §11, §14; hstspreload.org submission policy.
Bottom line: Preloading eliminates the first-visit downgrade window, but it is a one-way door — audit every subdomain's TLS readiness before submitting, because rollback is measured in months, not minutes.
HSTS (HTTP Strict Transport Security, RFC 6797) lets a site command browsers to use only HTTPS for a given duration via the Strict-Transport-Security header. But the header has a bootstrap flaw: the very first visit, before any header is seen, can be intercepted and downgraded. The preload list closes this gap — and introduces a sharper edge.
The preload list is a hardcoded set, compiled into Chromium and inherited by Firefox, Safari, and Edge, of domains that should be HTTPS-only from the first byte, no header required. To qualify, a site must serve the header with max-age of at least 31536000 (one year), the includeSubDomains directive, and the preload token.
Here is the under-discussed risk: removal is slow. Adding a domain is a code change shipped in a browser release; removing it is the same, plus the long tail of users who never update. A domain that preloads includeSubDomains commits every current and future subdomain to HTTPS. If an internal subdomain — a legacy device, an IoT management page, a vendor appliance — cannot serve a valid certificate, it becomes unreachable, and the fix takes browser-release cycles, often months.
Evidence vs. speculation: this is documented at hstspreload.org, which explicitly warns that submission is a long-term, hard-to-reverse commitment.
Further reading: RFC 6797 §11, §14; hstspreload.org submission policy.
Bottom line: Preloading eliminates the first-visit downgrade window, but it is a one-way door — audit every subdomain's TLS readiness before submitting, because rollback is measured in months, not minutes.
Why does the ACME DNS-01 challenge prove something HTTP-01 cannot?
Let's Encrypt automates issuance via ACME (Automatic Certificate Management Environment, RFC 8555). The protocol proves you control a domain through a challenge, and the choice between HTTP-01 and DNS-01 is not merely about convenience — they prove different scopes of control.
HTTP-01 asks the CA to fetch a token at http://your-domain/.well-known/acme-challenge/. Passing it proves you control the web server answering on port 80 for that exact hostname. It cannot issue wildcards, and it depends on inbound port 80 being reachable from the CA's validation network — which it deliberately performs from multiple network vantage points (multi-perspective validation, deployed 2020) to resist BGP-hijack-based fraud.
DNS-01 asks you to publish a TXT record at _acme-challenge.your-domain. Passing it proves control of the domain's DNS zone — a strictly broader authority. This is why DNS-01 is the only challenge that can issue wildcard certificates (*.example.com): a wildcard asserts control over an unbounded set of subdomains, which only zone-level control can substantiate.
Evidence vs. speculation: the wildcard-requires-DNS-01 rule is mandated by RFC 8555 §7.1.1 and Let's Encrypt policy, not an implementation quirk. The validation, not the issuance, is where the security lives.
Further reading: RFC 8555 §7.1, §8; Let's Encrypt multi-perspective validation announcement (2020).
Bottom line: HTTP-01 proves host-level control and fits single-name automation; DNS-01 proves zone-level control and is mandatory for wildcards — pick the challenge that matches the authority you actually need to assert.
Let's Encrypt automates issuance via ACME (Automatic Certificate Management Environment, RFC 8555). The protocol proves you control a domain through a challenge, and the choice between HTTP-01 and DNS-01 is not merely about convenience — they prove different scopes of control.
HTTP-01 asks the CA to fetch a token at http://your-domain/.well-known/acme-challenge/. Passing it proves you control the web server answering on port 80 for that exact hostname. It cannot issue wildcards, and it depends on inbound port 80 being reachable from the CA's validation network — which it deliberately performs from multiple network vantage points (multi-perspective validation, deployed 2020) to resist BGP-hijack-based fraud.
DNS-01 asks you to publish a TXT record at _acme-challenge.your-domain. Passing it proves control of the domain's DNS zone — a strictly broader authority. This is why DNS-01 is the only challenge that can issue wildcard certificates (*.example.com): a wildcard asserts control over an unbounded set of subdomains, which only zone-level control can substantiate.
Evidence vs. speculation: the wildcard-requires-DNS-01 rule is mandated by RFC 8555 §7.1.1 and Let's Encrypt policy, not an implementation quirk. The validation, not the issuance, is where the security lives.
Further reading: RFC 8555 §7.1, §8; Let's Encrypt multi-perspective validation announcement (2020).
Bottom line: HTTP-01 proves host-level control and fits single-name automation; DNS-01 proves zone-level control and is mandatory for wildcards — pick the challenge that matches the authority you actually need to assert.
Why does a browser silently load a mixed-content image but block a mixed-content script?
Mixed content occurs when an HTTPS page pulls a subresource over plain HTTP. Browsers do not treat all such resources identically; the distinction between passive and active mixed content is a deliberate threat-model decision codified in the W3C Mixed Content specification.
Passive (or "display") mixed content — images, audio, video — cannot alter the rest of the page's DOM or read its data. A network attacker tampering with an HTTP image can, at worst, swap the picture. Historically browsers loaded these with a warning indicator. The damage is bounded.
Active mixed content — scripts, stylesheets, iframes, fetch/XHR, WebSocket — executes in the page's origin. An attacker who rewrites an HTTP-loaded gains full control: stealing cookies, rewriting the DOM, exfiltrating form input. Because the blast radius is the entire origin, browsers block active mixed content outright, with no user override in modern engines.
The trajectory is toward eliminating the distinction. The Upgrade-Insecure-Requests CSP directive and autoupgrading (browsers silently rewriting http:// subresource URLs to https://) are closing the passive loophole, since a CSS file can leak data via background-image requests — blurring the passive/active line.
Evidence vs. speculation: the passive/active split is normative in the W3C spec; the autoupgrade rollout is the empirical direction of travel, not a guarantee for legacy resources.
Further reading: W3C Mixed Content (CR); CSP Level 3, upgrade-insecure-requests.
Bottom line: The split tracks blast radius — passive content can deface, active content can own the origin; rely on CSP upgrade directives rather than the browser's shrinking tolerance for either.
Mixed content occurs when an HTTPS page pulls a subresource over plain HTTP. Browsers do not treat all such resources identically; the distinction between passive and active mixed content is a deliberate threat-model decision codified in the W3C Mixed Content specification.
Passive (or "display") mixed content — images, audio, video — cannot alter the rest of the page's DOM or read its data. A network attacker tampering with an HTTP image can, at worst, swap the picture. Historically browsers loaded these with a warning indicator. The damage is bounded.
Active mixed content — scripts, stylesheets, iframes, fetch/XHR, WebSocket — executes in the page's origin. An attacker who rewrites an HTTP-loaded gains full control: stealing cookies, rewriting the DOM, exfiltrating form input. Because the blast radius is the entire origin, browsers block active mixed content outright, with no user override in modern engines.
The trajectory is toward eliminating the distinction. The Upgrade-Insecure-Requests CSP directive and autoupgrading (browsers silently rewriting http:// subresource URLs to https://) are closing the passive loophole, since a CSS file can leak data via background-image requests — blurring the passive/active line.
Evidence vs. speculation: the passive/active split is normative in the W3C spec; the autoupgrade rollout is the empirical direction of travel, not a guarantee for legacy resources.
Further reading: W3C Mixed Content (CR); CSP Level 3, upgrade-insecure-requests.
Bottom line: The split tracks blast radius — passive content can deface, active content can own the origin; rely on CSP upgrade directives rather than the browser's shrinking tolerance for either.
