UnityWebRequest Custom Certificate Validation: Missing Env Toggle
0 reputation · 03 Aug 2021, 06:28 UTC
0 reputation · 03 Aug 2021, 06:28 UTC
Developers often need to accept self‑signed certificates when connecting to local or staging servers. The current API requires a custom CertificateHandler subclass that overrides ValidateCertificate(byte[]) and embeds any environment‑based logic. There is no built‑in switch to automatically bypass validation for dev or staging domains, and the behavior varies across iOS, Android, and Windows, complicating cross‑platform builds.
In Unity 2023.x, iOS 15+ rejects incomplete chains even if a custom handler returns true, which raises the question of whether the networking module should honor the handler or enforce a stricter policy. The absence of a higher‑level API leaves the decision to the developer, increasing the risk of accidental exposure of insecure validation in production.
What would be the consequences of introducing a global AllowInsecureCertificates flag scoped to a domain list? How could such a flag be safely gated behind build or runtime configuration to avoid accidental leakage? Would a dedicated UnityWebRequest.SetInsecureDomains method simplify the current pattern?
34775 reputation · 03 Aug 2021, 13:24 UTC
A global AllowInsecureCertificates flag scoped to a domain list would centralize logic that today lives in ad-hoc CertificateHandler subclasses, but it would not remove the underlying risk: any bypass that ships in a release binary is exploitable, and on iOS 15+ the platform can reject an incomplete chain before your handler's return value matters. A flag changes who can make the mistake, not whether the mistake is possible.
Confirmed behavior (well-established): UnityWebRequest has no built-in environment toggle. Accepting a self-signed certificate requires subclassing CertificateHandler and overriding ValidateCertificate(byte[]), then assigning it to unityWebRequest.certificateHandler. There is no public SetInsecureDomains API in current Unity LTS lines.
Likely, but verify on device: The claim that iOS 15+ rejects incomplete chains even when ValidateCertificate returns true is plausible — App Transport Security and the native URL loading stack perform their own evaluation, and Unity's handler sits on top of platform TLS behavior that differs per backend (NSURLSession on iOS, platform-specific stacks on Android and Windows). Treat the exact iOS interaction as needs device verification; do not design around it from documentation alone.
*.staging.example.com), and wildcard or suffix matching can be abused via DNS rebinding/spoofing in hostile networks — exactly the networks where TLS matters most.Gate the handler at compile time so the bypass code is not present in release binaries at all:
public class DevCertHandler : CertificateHandler
{
protected override bool ValidateCertificate(byte[] certificateData) => true;
}
UnityWebRequest req = UnityWebRequest.Get(url);
#if DEV_INSECURE_TLS
// Only defined in a dedicated dev build configuration, never in release.
if (IsAllowedDevHost(req.uri.Host))
req.certificateHandler = new DevCertHandler();
#endif
Key properties of this pattern:
#if block cannot. Verify by building a release player and confirming the define is unset.Marginally, as ergonomics — but only if it were implemented as per-request, exact-host, and compiled out of release builds by default. A global static method would reproduce every risk above with a friendlier name. Until such an API exists, the conditional-compilation handler above achieves the same result with stronger guarantees.
Before relying on any bypass for iOS staging: log inside ValidateCertificate on a physical iOS 15+ device against your staging server. If the callback never fires and the request still fails, the platform is rejecting the chain independently, and no Unity-level flag will fix it — you would need a properly chained staging certificate instead.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.