Skip to content

Commit 3880b62

Browse files
authored
fix: MCP server accepts malformed IPv6 loopback hosts (#1180)
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
1 parent adef8fc commit 3880b62

2 files changed

Lines changed: 31 additions & 2 deletions

File tree

‎src/OpenClaw.Shared/Mcp/McpHttpServer.cs‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Diagnostics;
4+
using System.Globalization;
45
using System.IO;
56
using System.Net;
67
using System.Security.Cryptography;
@@ -762,7 +763,7 @@ private static bool IsAuthorized(string authToken, string? authHeader)
762763
Encoding.UTF8.GetBytes(authToken));
763764
}
764765

765-
private static bool IsHostAllowed(string? host)
766+
internal static bool IsHostAllowed(string? host)
766767
{
767768
if (string.IsNullOrEmpty(host)) return false;
768769
var trimmed = host.Trim();
@@ -772,7 +773,17 @@ private static bool IsHostAllowed(string? host)
772773
var closeBracket = trimmed.IndexOf(']');
773774
if (closeBracket < 0) return false;
774775
var v6 = trimmed.Substring(1, closeBracket - 1);
775-
return string.Equals(v6, "::1", StringComparison.Ordinal);
776+
if (!string.Equals(v6, "::1", StringComparison.Ordinal)) return false;
777+
778+
var suffix = trimmed.AsSpan(closeBracket + 1);
779+
if (suffix.IsEmpty) return true;
780+
return suffix.Length > 1
781+
&& suffix[0] == ':'
782+
&& ushort.TryParse(
783+
suffix[1..],
784+
NumberStyles.None,
785+
CultureInfo.InvariantCulture,
786+
out _);
776787
}
777788
// IPv4 / hostname: strip trailing :port if present.
778789
var colon = trimmed.LastIndexOf(':');

‎tests/OpenClaw.Shared.Tests/McpHttpServerTests.cs‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,24 @@ public async Task Post_WithRebindHost_RejectedWithForbidden()
204204
finally { server.Dispose(); http.Dispose(); }
205205
}
206206

207+
[Theory]
208+
[InlineData("[::1]")]
209+
[InlineData("[::1]:8765")]
210+
public void IsHostAllowed_AcceptsBracketedIpv6Loopback(string host)
211+
{
212+
Assert.True(McpHttpServer.IsHostAllowed(host));
213+
}
214+
215+
[Theory]
216+
[InlineData("[::1]evil")]
217+
[InlineData("[::1]:")]
218+
[InlineData("[::1]:not-a-port")]
219+
[InlineData("[::1]:65536")]
220+
public void IsHostAllowed_RejectsMalformedBracketedIpv6Loopback(string host)
221+
{
222+
Assert.False(McpHttpServer.IsHostAllowed(host));
223+
}
224+
207225
[Fact]
208226
public async Task Post_WithLocalhostHost_Accepted()
209227
{

0 commit comments

Comments
 (0)