{"record":{"id":"69f3b54598946d12","repo":"microsoft/semantic-kernel","slug":"sending-requests-to-host-uri-host-is-not-allowed-add-the","errorCode":null,"errorMessage":"Sending requests to host '{uri.Host}' is not allowed. Add the host to AllowedDomains.","messagePattern":"Sending requests to host '(.+?)' is not allowed\\. Add the host to AllowedDomains\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Plugins/Plugins.Core/CodeInterpreter/SessionsPythonPlugin.cs","lineNumber":281,"sourceCode":"    /// Sends an HTTP request to the specified path with the specified method and content.\n    /// </summary>\n    /// <param name=\"httpClient\">The HTTP client to use.</param>\n    /// <param name=\"method\">The HTTP method to use.</param>\n    /// <param name=\"path\">The path to send the request to.</param>\n    /// <param name=\"cancellationToken\">The cancellation token.</param>\n    /// <param name=\"httpContent\">The content to send with the request.</param>\n    /// <returns>The HTTP response message.</returns>\n    private async Task<HttpResponseMessage> SendAsync(HttpClient httpClient, HttpMethod method, string path, CancellationToken cancellationToken, HttpContent? httpContent = null)\n    {\n        // The query string is the same for all operations\n        var pathWithQueryString = $\"{path}?identifier={this._settings.SessionId}&api-version={ApiVersion}\";\n\n        var uri = new Uri(this._poolManagementEndpoint, pathWithQueryString);\n\n        // Deny requests unless the endpoint host is explicitly allowed.\n        if (this._settings.AllowedDomains?.Contains(uri.Host, StringComparer.OrdinalIgnoreCase) != true)\n        {\n            throw new InvalidOperationException(\n                $\"Sending requests to host '{uri.Host}' is not allowed. Add the host to {nameof(SessionsPythonSettings.AllowedDomains)}.\");\n        }\n\n        using var request = new HttpRequestMessage(method, uri)\n        {\n            Content = httpContent,\n        };\n\n        await this.AddHeadersAsync(request, cancellationToken).ConfigureAwait(false);\n\n        return await httpClient.SendWithSuccessCheckAsync(request, cancellationToken).ConfigureAwait(false);\n    }\n\n    /// <summary>\n    /// Validates that the local file path is within allowed upload directories.\n    /// </summary>\n    /// <param name=\"localFilePath\">The local file path to validate.</param>\n    /// <returns>The canonicalized path if valid.</returns>","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/ca40aa7226531d28a721d0ca0e451d0aaf86dafc/dotnet/src/Plugins/Plugins.Core/CodeInterpreter/SessionsPythonPlugin.cs#L263-L299","documentation":"Thrown by SessionsPythonPlugin.SendAsync when the resolved host of the Code Interpreter pool management endpoint is not present in SessionsPythonSettings.AllowedDomains. The plugin enforces an explicit domain allowlist so requests are never sent to unintended hosts. If AllowedDomains is null/empty or does not contain uri.Host (case-insensitive), the request is rejected before any HTTP call is made.","triggerScenarios":"Any SessionsPythonPlugin API call (e.g. RunCodeAsync) that invokes SendAsync where the host from new Uri(_poolManagementEndpoint, pathWithQueryString) is not in _settings.AllowedDomains — most often because AllowedDomains was never configured or lists the wrong host (e.g. missing a project-specific *.openai.azure.com or codeinterpreter endpoint hostname).","commonSituations":"Forgetting to set AllowedDomains at all when constructing SessionsPythonSettings; copying a sample config whose domain differs from your deployed region/host; a redirect or different pool management hostname than the one allowlisted; using localhost in dev while allowlisting only production domains (or vice versa); host casing or port variants you assumed were covered.","solutions":["Add the exact host reported in the message to SessionsPythonSettings.AllowedDomains (case-insensitive match, host only, no scheme/port).","If AllowedDomains was null, initialize it with your Code Interpreter management endpoint host, e.g. new List<string> { \"<region>.codeinterpreter.azure.com\" }.","Verify _poolManagementEndpoint is correct in your configuration; a wrong endpoint yields an unexpected host not in the allowlist.","If you intentionally need to allow all hosts (dev/test only), add the specific hosts you use; there is no wildcard bypass shown in SendAsync, so keep the list aligned with every environment."],"exampleFix":"// before\nvar settings = new SessionsPythonSettings\n{\n    PoolManagementEndpoint = new Uri(\"https://my-pool.eastus.codeinterpreter.azure.com\")\n};\n\n// after\nvar settings = new SessionsPythonSettings\n{\n    PoolManagementEndpoint = new Uri(\"https://my-pool.eastus.codeinterpreter.azure.com\"),\n    AllowedDomains = new List<string> { \"my-pool.eastus.codeinterpreter.azure.com\" }\n};","handlingStrategy":"validation","validationCode":"var host = new Uri(settings.PoolManagementEndpoint).Host;\nif (settings.AllowedDomains?.Contains(host, StringComparer.OrdinalIgnoreCase) != true)\n    throw new InvalidOperationException(\n        $\"AllowedDomains must contain the pool management host '{host}' before using SessionsPythonPlugin.\");","typeGuard":null,"tryCatchPattern":"try\n{\n    await plugin.RunCodeAsync(code);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"AllowedDomains\"))\n{\n    logger.LogError(ex, \"Code Interpreter host is not allowlisted. Add it to SessionsPythonSettings.AllowedDomains.\");\n}","preventionTips":["Always populate AllowedDomains in the same place you set PoolManagementEndpoint.","Derive AllowedDomains programmatically from the endpoint host instead of hardcoding a separate value.","Add a startup/config validation step that fails fast when the allowlist is null or empty.","When changing environments (dev/staging/prod), re-check that each region's host is in the allowlist."],"tags":["security","configuration","http","allowlist","dotnet"],"backgroundTag":"invalid-config-value","analyzedSha":"ca40aa7226531d28a721d0ca0e451d0aaf86dafc","analyzedAt":"2026-09-20T21:26:31.973Z","contentChangedAt":"2026-09-20T21:26:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}