using System.Net; using System.Net.Http; using ClawdDotNet.Tools.WebFetch; using Shouldly; namespace ClawdDotNet.Tools.Tests.WebFetch; /// /// #580: Die Pruefung der URL sieht nur den Namen. localtest.me steht auf keiner Sperrliste /// und loest auf 127.0.0.1 auf - im Pruefdurchgang oeffnete WebFetch damit eine Verbindung /// auf Loopback. Geprueft wird deshalb die aufgeloeste Adresse, ohne echtes Netz. /// public sealed class UrlGuardAufloesungTests { private static Func> Aufloesung(params string[] adressen) => (_, _) => Task.FromResult(adressen.Select(IPAddress.Parse).ToArray()); [Theory] [InlineData("127.0.0.1")] [InlineData("192.168.40.48")] [InlineData("169.254.169.254")] [InlineData("::1")] [InlineData("::ffff:10.0.0.5")] public async Task Ein_Name_der_ins_lokale_Netz_aufloest_wird_gesperrt(string adresse) { var ex = await Should.ThrowAsync( () => UrlGuard.ResolveAllowedAsync("localtest.me", Aufloesung(adresse), default)); ex.Message.ShouldContain("localtest.me"); ex.Message.ShouldContain("blocked"); } [Fact] public async Task Ein_Name_mit_oeffentlicher_und_interner_Adresse_wird_gesperrt() { // Genau das Muster, mit dem man eine Stichprobenpruefung ueberlistet. await Should.ThrowAsync( () => UrlGuard.ResolveAllowedAsync("gemischt.example", Aufloesung("93.184.215.14", "127.0.0.1"), default)); } [Fact] public async Task Ein_Name_mit_oeffentlichen_Adressen_wird_zugelassen() { var adressen = await UrlGuard.ResolveAllowedAsync( "example.com", Aufloesung("93.184.215.14", "2606:2800:21f:cb07:6820:80da:af6b:8b2c"), default); adressen.Length.ShouldBe(2); } [Fact] public async Task Ein_IP_Literal_wird_ohne_Aufloesung_geprueft() { var aufgerufen = false; await Should.ThrowAsync(() => UrlGuard.ResolveAllowedAsync( "[::1]", (_, _) => { aufgerufen = true; return Task.FromResult(Array.Empty()); }, default)); aufgerufen.ShouldBeFalse(); } [Fact] public async Task Ein_Name_ohne_Adresse_wird_nicht_verbunden() => await Should.ThrowAsync( () => UrlGuard.ResolveAllowedAsync("nirgends.example", Aufloesung(), default)); }