microsoft/semantic-kernel · critical · KernelException

The operation path resolves to '{requestPath}', which is out

Error message

The operation path resolves to '{requestPath}', which is outside the configured server base path '{basePath}'.

What it means

Companion SSRF guard in EnsureRequestTargetMatchesServer. After the authority check passes, the absolute path of the resolved request URL is compared to the server's base path. If the request path neither equals the base path (minus trailing slash) nor starts with it, the operation path has escaped the server's base path, and the request is rejected.

Source

Thrown at dotnet/src/Functions/Functions.OpenApi/Model/RestApiOperation.cs:205

    /// <param name="requestUrl">The request URL produced by combining the server URL and operation path.</param>
    private static void EnsureRequestTargetMatchesServer(Uri serverUrl, Uri requestUrl)
    {
        var serverAuthority = serverUrl.GetLeftPart(UriPartial.Authority);
        var requestAuthority = requestUrl.GetLeftPart(UriPartial.Authority);

        if (!string.Equals(serverAuthority, requestAuthority, StringComparison.OrdinalIgnoreCase))
        {
            throw new KernelException($"The operation path resolves to '{requestAuthority}', which does not match the configured server '{serverAuthority}'.");
        }

        // GetServerUrl guarantees a trailing slash, so the server's base path always ends with '/'.
        var basePath = serverUrl.AbsolutePath;
        var requestPath = requestUrl.AbsolutePath;

        if (!string.Equals(requestPath, basePath.TrimEnd('/'), StringComparison.Ordinal) &&
            !requestPath.StartsWith(basePath, StringComparison.Ordinal))
        {
            throw new KernelException($"The operation path resolves to '{requestPath}', which is outside the configured server base path '{basePath}'.");
        }
    }

    /// <summary>
    /// Builds operation request headers.
    /// </summary>
    /// <param name="arguments">The operation arguments.</param>
    /// <returns>The request headers.</returns>
    internal IDictionary<string, string> BuildHeaders(IDictionary<string, object?> arguments)
    {
        var headers = new Dictionary<string, string>();

        var parameters = this.Parameters.Where(p => p.Location == RestApiParameterLocation.Header);

        foreach (var parameter in parameters)
        {
            var argument = this.GetArgumentForParameter(arguments, parameter);
            if (argument == null)

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Align operation paths with the server's declared base path (paths should be relative and sit under the server's prefix).
  2. Make sure no path contains traversal sequences; note ValidatePathSegments separately rejects '..' but this guard catches residual escapes after canonicalization.
  3. If a different base path is genuinely needed, add it as an additional server entry rather than escaping the first one.
  4. Audit the spec's servers[].url and every path to confirm prefix containment.

Example fix

// before - server has a base path but the operation path escapes it
"servers": [ { "url": "https://api.example.com/v1/" } ],
"paths": { "/v2/items": { } }

// after - operation path lives under the base path
"servers": [ { "url": "https://api.example.com/v1/" } ],
"paths": { "/items": { } }
Defensive patterns

Strategy: validation

Validate before calling

var basePath = serverUrl.AbsolutePath;
foreach (var pathKey in doc.Paths.Keys)
{
    var resolved = new Uri(serverUrl, pathKey.TrimStart('/')).AbsolutePath;
    if (!resolved.Equals(basePath.TrimEnd('/'), StringComparison.Ordinal) && !resolved.StartsWith(basePath, StringComparison.Ordinal))
        throw new InvalidOperationException($"Path '{pathKey}' escapes server base path '{basePath}'.");
}

Type guard

static bool PathWithinBase(Uri serverUrl, string opPath)
{
    var basePath = serverUrl.AbsolutePath;
    var resolved = new Uri(serverUrl, opPath.TrimStart('/')).AbsolutePath;
    return resolved.Equals(basePath.TrimEnd('/'), StringComparison.Ordinal) || resolved.StartsWith(basePath, StringComparison.Ordinal);
}

Try / catch

try { var url = operation.BuildOperationUrl(arguments); }
catch (KernelException ex) when (ex.Message.Contains("outside the configured server base path"))
{ logger.LogWarning("Operation path escapes server base path; fix the spec."); throw; }

Prevention

When it happens

Trigger: A server URL with a base path (e.g. 'https://api.example.com/v1/') combined with an operation path that resolves outside /v1/ - e.g. a path of /../v2/resource that, after the dot-segment is canonicalized, lands in a sibling base path. Also an absolute path like /other/resource that ignores the server's /v1/ prefix.

Common situations: Spec authored with paths that ignore the server base path; a path-traversal-style template; merging specs with different base-path conventions.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/ba0a73d27d0e2a5c. Report an issue: GitHub.