microsoft/semantic-kernel · error · KernelException

The address '{address}' is not allowed for the '{operation.N

Error message

The address '{address}' is not allowed for the '{operation.Name}' gRPC operation. The address must match one of the allowed base addresses.

What it means

Thrown when `_allowedAddresses` is configured (non-empty) and the resolved operation address does not prefix-match any allowed base address with a proper boundary (`/`, `?`, or `#` after the prefix). This is an SSRF guard: even with a valid scheme, the destination must fall under a whitelisted base.

Source

Thrown at dotnet/src/Functions/Functions.Grpc/GrpcOperationRunner.cs:215

                {
                    // If the allowed URI already ends at a boundary (e.g., trailing '/'),
                    // or the full URIs match exactly, no further check is needed.
                    // Otherwise, ensure the next character is a path boundary to prevent
                    // prefix bypasses (e.g., allowed "https://host/grpc" should not match "https://host/grpcevil").
                    int prefixLength = allowedUri.Length;
                    if (prefixLength >= addressUri.AbsoluteUri.Length ||
                        allowedUri[prefixLength - 1] is '/' ||
                        addressUri.AbsoluteUri[prefixLength] is '/' or '?' or '#')
                    {
                        isAllowed = true;
                        break;
                    }
                }
            }

            if (!isAllowed)
            {
                throw new KernelException($"The address '{address}' is not allowed for the '{operation.Name}' gRPC operation. The address must match one of the allowed base addresses.");
            }
        }

        return address!;
    }

    /// <summary>
    /// Creates a marshaller - a typed abstraction for gRPC message serialization and deserialization.
    /// </summary>
    /// <param name="contractType">The message contract data type.</param>
    /// <returns>The marshaller.</returns>
    private Marshaller<T> CreateMarshaller<T>(Type contractType)
    {
        byte[] Serialize(T instance)
        {
            using var memoryStream = new MemoryStream();

            Serializer.NonGeneric.Serialize(memoryStream, instance);

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Point the address at a URL that starts with (and is bounded by) an allowed base address.
  2. Add the service's base address to AllowedAddresses in GrpcOperationRunnerOptions.
  3. Ensure the allow-list entry ends with `/` if the base is a path prefix.

Example fix

// before
// allowed = [https://api.example.com/], address = https://api2.example.com/v1
// after
options.AllowedAddresses = new[] { new Uri("https://api2.example.com/") };
// or use an already-allowed host
Defensive patterns

Strategy: validation

Validate before calling

bool allowed(Uri addr, IEnumerable<Uri> bases) =>
    bases.Any(b => addr.AbsoluteUri.StartsWith(b.AbsoluteUri, StringComparison.OrdinalIgnoreCase));

Prevention

When it happens

Trigger: Allowed base is `https://internal.example.com/` and the address is `https://internal.example.com.evil.com/` (no boundary) or `https://other.example.com/` (no match).

Common situations: Address override pointing outside the approved base; production allow-list missing the new service host after a migration; trailing-slash mismatch between allow-list entry and address.

Related errors


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