1. Describe the bug
We're experiencing issues with failing internal HTTP requests between two OnPrem BC-Containers ( using SSL with Self-Signed Certificates )after upgrading from 27.3 to 27.4. Downgrading back to 27.3 provides a temporary fix.
2. To Reproduce
Create two BC 27.4 Containers and call one's API from the other.
procedure GetCompanies(InstanceUrl: Text; Username: Text; Password: Text; var Companies: List of [Text])
var
l_HttpClient: HttpClient;
l_HttpRequestMessage: HttpRequestMessage;
l_HttpResponseMessage: HttpResponseMessage;
l_Headers: HttpHeaders;
l_AuthText: Text;
l_Base64Convert: Codeunit "Base64 Convert";
l_Url: Text;
l_ResponseText: Text;
l_JsonToken: JsonToken;
l_JsonArray: JsonArray;
l_JsonValue: JsonToken;
l_CompanyName: Text;
i: Integer;
begin
Clear(Companies);
// Use the correct API v2.0 endpoint
l_Url := InstanceUrl.TrimEnd('/') + '/api/v2.0/companies';
// Build auth header
l_AuthText := l_Base64Convert.ToBase64(Username + ':' + Password);
l_HttpClient.UseServerCertificateValidation(false);
l_HttpRequestMessage.Method := 'GET';
l_HttpRequestMessage.SetRequestUri(l_Url);
l_HttpRequestMessage.GetHeaders(l_Headers);
l_Headers.Add('Authorization', 'Basic ' + l_AuthText);
if not l_HttpClient.Send(l_HttpRequestMessage, l_HttpResponseMessage) then
Error('Failed to connect to %1', l_Url);
if not l_HttpResponseMessage.IsSuccessStatusCode then
Error('Failed to get companies. Status: %1 %2', l_HttpResponseMessage.HttpStatusCode, l_HttpResponseMessage.ReasonPhrase);
l_HttpResponseMessage.Content.ReadAs(l_ResponseText);
if not l_JsonToken.ReadFrom(l_ResponseText) then
Error('Invalid JSON response');
if not l_JsonToken.AsObject().Get('value', l_JsonToken) then
Error('No value array in response');
l_JsonArray := l_JsonToken.AsArray();
for i := 0 to l_JsonArray.Count - 1 do begin
l_JsonArray.Get(i, l_JsonValue);
if l_JsonValue.AsObject().Get('name', l_JsonToken) then begin
l_CompanyName := l_JsonToken.AsValue().AsText();
Companies.Add(l_CompanyName);
end;
end;
end;
3. Expected behavior
Retrieve the companies from our target environment.
4. Actual behavior
5. Versions:
- AL Language: latest
- Visual Studio Code: latest
- Business Central: 27.4
- List of Visual Studio Code extensions that you have installed:
- Operating System:
Here is the Eventlog and a Claude analysation:
EventLogHttpCallFail.csv
Claude's Response:
Analysis: Anti-SSRF Protection Blocking Internal HTTP Calls
The log shows a clear pattern — all 3 calls fail identically. Here's the chain of events for each call:
Error Sequence (per call)
AntiSSRFWrapper.cs — Non routable address detected: 10.11.42.206 / 10.11.42.205AntiSSRFHandler.cs — SSRF violation detected: non routable network address.- HTTP response —
Status code = 0 (0) (request never sent) - Exception —
NavNCLDialogException bubbles up from Codeunit51148.GetCompanies → Page51178
Root Cause
BC 27.4 introduced (or enforced) Anti-SSRF (Server-Side Request Forgery) protection in the HTTP client pipeline. This new AntiSSRFHandler intercepts outgoing HTTP requests, resolves the target hostname to an IP, and blocks requests to private/non-routable IP ranges.
Your internal hostnames resolve to RFC 1918 private addresses:
Hostname | IP | Range
-- | -- | --
bc-prelive.sw.buhl-data.com | 10.11.42.206 | 10.0.0.0/8 (private)
bc-live.sw.buhl-data.com | 10.11.42.205 | 10.0.0.0/8 (private)
The AntiSSRFHandler.SendAsync (line 114) checks the resolved IP before the request leaves the server and kills it with status code 0 if it targets a private network.
Why 27.3 Works
In 27.3, the AntiSSRFHandler either didn't exist or wasn't enforced for on-premises server-to-server calls. Microsoft tightened this in 27.4, likely as part of their ongoing security hardening (this is a standard cloud-security measure to prevent extensions from reaching internal infrastructure).
Fix Options
Server configuration — In the BC Server CustomSettings.config, look for a setting like:
<textarea class="ime-text-area" readonly="true" tabindex="-1" aria-hidden="true" style="min-width: 0px; min-height: 0px; margin: 0px; padding: 0px; position: absolute; resize: none; border: none; overflow: hidden; color: transparent; background-color: transparent; z-index: -10; outline: none !important;"></textarea>
or use the Set-NAVServerConfiguration PowerShell cmdlet. The exact key name may vary — check the 27.4 release notes or CustomSettings.config for any new Anti-SSRF / "NonRoutable" / "PrivateNetwork" settings.
Reverse proxy with a public IP — Put a reverse proxy (e.g., nginx, IIS ARR) in front of the target BC instances that has a public/routable IP, and point your DNS there.
Use localhost / loopback exception — If the caller and target run on the same machine, localhost may be exempted (though this likely won't apply to your setup).
Recommended first step: Check the BC 27.4 server configuration file on the calling instance for new Anti-SSRF settings and enable the exception for private network addresses.
1. Describe the bug
We're experiencing issues with failing internal HTTP requests between two OnPrem BC-Containers ( using SSL with Self-Signed Certificates )after upgrading from 27.3 to 27.4. Downgrading back to 27.3 provides a temporary fix.
2. To Reproduce
Create two BC 27.4 Containers and call one's API from the other.
3. Expected behavior
Retrieve the companies from our target environment.
4. Actual behavior
5. Versions:
Here is the Eventlog and a Claude analysation:
EventLogHttpCallFail.csv
Claude's Response:
Analysis: Anti-SSRF Protection Blocking Internal HTTP Calls
The log shows a clear pattern — all 3 calls fail identically. Here's the chain of events for each call:
Error Sequence (per call)
AntiSSRFWrapper.cs—Non routable address detected: 10.11.42.206/10.11.42.205AntiSSRFHandler.cs—SSRF violation detected: non routable network address.Status code = 0 (0)(request never sent)NavNCLDialogExceptionbubbles up fromCodeunit51148.GetCompanies→Page51178Root Cause
BC 27.4 introduced (or enforced) Anti-SSRF (Server-Side Request Forgery) protection in the HTTP client pipeline. This new
AntiSSRFHandlerintercepts outgoing HTTP requests, resolves the target hostname to an IP, and blocks requests to private/non-routable IP ranges.Your internal hostnames resolve to RFC 1918 private addresses:
Hostname | IP | Range -- | -- | -- bc-prelive.sw.buhl-data.com | 10.11.42.206 | 10.0.0.0/8 (private) bc-live.sw.buhl-data.com | 10.11.42.205 | 10.0.0.0/8 (private)The
AntiSSRFHandler.SendAsync(line 114) checks the resolved IP before the request leaves the server and kills it with status code 0 if it targets a private network.Why 27.3 Works
In 27.3, the
AntiSSRFHandlereither didn't exist or wasn't enforced for on-premises server-to-server calls. Microsoft tightened this in 27.4, likely as part of their ongoing security hardening (this is a standard cloud-security measure to prevent extensions from reaching internal infrastructure).Fix Options
Server configuration — In the BC Server
CustomSettings.config, look for a setting like:or use the
Set-NAVServerConfigurationPowerShell cmdlet. The exact key name may vary — check the 27.4 release notes orCustomSettings.configfor any new Anti-SSRF / "NonRoutable" / "PrivateNetwork" settings.Reverse proxy with a public IP — Put a reverse proxy (e.g., nginx, IIS ARR) in front of the target BC instances that has a public/routable IP, and point your DNS there.
Use
localhost/ loopback exception — If the caller and target run on the same machine, localhost may be exempted (though this likely won't apply to your setup).Recommended first step: Check the BC 27.4 server configuration file on the calling instance for new Anti-SSRF settings and enable the exception for private network addresses.