Scoping certificate-validation bypass in a PowerShell DNS/TLS triage script that must run on 5.1 and 7
0 reputation · 22 Jul 2026, 17:44 UTC
0 reputation · 22 Jul 2026, 17:44 UTC
I am designing a diagnostic script that separates DNS resolution failures from TLS certificate-validation failures when an internal HTTPS endpoint is unreachable. It uses Resolve-DnsName with -Server and -DnsOnly to compare resolvers, then Test-NetConnection -Port 443 -InformationLevel Detailed, and finally Invoke-RestMethod to surface the TLS error.
The script must run on both Windows PowerShell 5.1 and PowerShell 7. On 7, -SkipCertificateCheck gives a per-request bypass for confirming that an error is certificate validation rather than connectivity. On 5.1 the only equivalent I know is overriding [System.Net.ServicePointManager]::ServerCertificateValidationCallback, which is process-global and persists for the session. I also want the script to inspect the served chain via SslStream.AuthenticateAsClient so I can check expiry, chain Build() status, and hostname match instead of blindly bypassing.
The unresolved decision is whether the tool should relax validation at all, or only report the chain problem and leave trust fixes (installing the missing root/intermediate CA) to the operator, since a bypass masks real man-in-the-middle risk.
35275 reputation · 22 Jul 2026, 23:27 UTC
In PowerShell 5.1 there is no built‑in per‑request switch to skip certificate validation; the only supported way is the process‑global [System.Net.ServicePointManager]::ServerCertificateValidationCallback. You can emulate a request‑scoped bypass by saving the current callback, installing a temporary delegate, making the request, then restoring the original callback. This approach works only when no other .NET HTTP calls happen in the interval and is not thread‑safe.
Invoke‑RestMethod and Invoke‑WebRequest accept -SkipCertificateCheck, which sets an HttpClientHandler.ServerCertificateCustomValidationCallback limited to that cmdlet’s scope.ServerCertificateValidationCallback property is process‑global; there is no native per‑request alternative.Resolve‑DnsName returns objects with the same core properties (Name, Type, TTL, Section, IPAddress) on Windows, Linux and macOS when run under PowerShell 7; only optional IPv6‑specific fields may differ and do not affect basic parsing.if ($PSVersionTable.PSMajor -ge 7) { … } else { … }.Invoke‑RestMethod -Uri $uri -SkipCertificateCheck to test connectivity while ignoring validation, then run a second request without the switch to see if validation fails.$orig = [System.Net.ServicePointManager]::ServerCertificateValidationCallback.$true (or performs custom chain checks): $temp = { param($sender,$cert,$chain,$sslPolicyErrors) $true }.[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $temp.Invoke‑RestMethod (or [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 if needed).[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $orig.Resolve‑DnsName -Name $host -Server -DnsOnly on both the configured resolver and a public resolver (e.g., 8.8.8.8) and compare the IPAddress values to separate DNS failures from TLS failures.[System.Net.Security.SslStream] to report expiry, build status, and hostname match without relying on a bypass.Will the script ever run multiple instances concurrently (e.g., background jobs or parallel runspaces)? If yes, the global‑callback method in 5.1 is not thread‑safe and you would need to isolate each run in its own PowerShell process or use a locking mechanism.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.