mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-08-09 05:49:24 +00:00
fix: add Uri.EscapeDataString to service URL path interpolations
VmService, ContainerService, StorageService, and SnapshotService now wrap user-controlled string parameters (node names, storage names) with Uri.EscapeDataString() in URL path construction, preventing path traversal or encoding issues. Integer parameters (vmid) are left unwrapped. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -25,7 +25,7 @@ namespace PSProxmoxVE.Core.Services
|
||||
if (string.IsNullOrWhiteSpace(node)) throw new ArgumentNullException(nameof(node));
|
||||
|
||||
using var client = new PveHttpClient(session);
|
||||
var response = client.GetAsync($"nodes/{node}/qemu/{vmid}/snapshot")
|
||||
var response = client.GetAsync($"nodes/{Uri.EscapeDataString(node)}/qemu/{vmid}/snapshot")
|
||||
.GetAwaiter().GetResult();
|
||||
var data = JObject.Parse(response)["data"];
|
||||
return data?.ToObject<PveSnapshot[]>() ?? Array.Empty<PveSnapshot>();
|
||||
@@ -61,7 +61,7 @@ namespace PSProxmoxVE.Core.Services
|
||||
formData["description"] = description!;
|
||||
|
||||
using var client = new PveHttpClient(session);
|
||||
var response = client.PostAsync($"nodes/{node}/qemu/{vmid}/snapshot", formData)
|
||||
var response = client.PostAsync($"nodes/{Uri.EscapeDataString(node)}/qemu/{vmid}/snapshot", formData)
|
||||
.GetAwaiter().GetResult();
|
||||
return ParseTask(response, node);
|
||||
}
|
||||
@@ -84,7 +84,7 @@ namespace PSProxmoxVE.Core.Services
|
||||
if (string.IsNullOrWhiteSpace(snapname)) throw new ArgumentNullException(nameof(snapname));
|
||||
|
||||
using var client = new PveHttpClient(session);
|
||||
var response = client.DeleteAsync($"nodes/{node}/qemu/{vmid}/snapshot/{Uri.EscapeDataString(snapname)}")
|
||||
var response = client.DeleteAsync($"nodes/{Uri.EscapeDataString(node)}/qemu/{vmid}/snapshot/{Uri.EscapeDataString(snapname)}")
|
||||
.GetAwaiter().GetResult();
|
||||
return ParseTask(response, node);
|
||||
}
|
||||
@@ -107,7 +107,7 @@ namespace PSProxmoxVE.Core.Services
|
||||
if (string.IsNullOrWhiteSpace(snapname)) throw new ArgumentNullException(nameof(snapname));
|
||||
|
||||
using var client = new PveHttpClient(session);
|
||||
var response = client.PostAsync($"nodes/{node}/qemu/{vmid}/snapshot/{Uri.EscapeDataString(snapname)}/rollback")
|
||||
var response = client.PostAsync($"nodes/{Uri.EscapeDataString(node)}/qemu/{vmid}/snapshot/{Uri.EscapeDataString(snapname)}/rollback")
|
||||
.GetAwaiter().GetResult();
|
||||
return ParseTask(response, node);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace PSProxmoxVE.Core.Services
|
||||
if (session == null) throw new ArgumentNullException(nameof(session));
|
||||
|
||||
var resource = node != null
|
||||
? $"nodes/{node}/storage"
|
||||
? $"nodes/{Uri.EscapeDataString(node)}/storage"
|
||||
: "storage";
|
||||
|
||||
using var client = new PveHttpClient(session);
|
||||
@@ -57,7 +57,7 @@ namespace PSProxmoxVE.Core.Services
|
||||
if (string.IsNullOrWhiteSpace(node)) throw new ArgumentNullException(nameof(node));
|
||||
if (string.IsNullOrWhiteSpace(storage)) throw new ArgumentNullException(nameof(storage));
|
||||
|
||||
var resource = $"nodes/{node}/storage/{storage}/content";
|
||||
var resource = $"nodes/{Uri.EscapeDataString(node)}/storage/{Uri.EscapeDataString(storage)}/content";
|
||||
if (!string.IsNullOrEmpty(contentType))
|
||||
resource += $"?content={Uri.EscapeDataString(contentType!)}";
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace PSProxmoxVE.Core.Services
|
||||
|
||||
using var client = new PveHttpClient(session);
|
||||
var response = client.UploadFileAsync(
|
||||
$"nodes/{node}/storage/{storage}/upload",
|
||||
$"nodes/{Uri.EscapeDataString(node)}/storage/{Uri.EscapeDataString(storage)}/upload",
|
||||
filePath,
|
||||
formFields,
|
||||
checksum,
|
||||
@@ -144,7 +144,7 @@ namespace PSProxmoxVE.Core.Services
|
||||
};
|
||||
|
||||
using var client = new PveHttpClient(session);
|
||||
var response = client.PostAsync($"nodes/{node}/storage/{storage}/download-url", formData)
|
||||
var response = client.PostAsync($"nodes/{Uri.EscapeDataString(node)}/storage/{Uri.EscapeDataString(storage)}/download-url", formData)
|
||||
.GetAwaiter().GetResult();
|
||||
return ParseTask(response, node);
|
||||
}
|
||||
@@ -184,7 +184,7 @@ namespace PSProxmoxVE.Core.Services
|
||||
if (string.IsNullOrWhiteSpace(storage)) throw new ArgumentNullException(nameof(storage));
|
||||
|
||||
using var client = new PveHttpClient(session);
|
||||
client.DeleteAsync($"storage/{storage}").GetAwaiter().GetResult();
|
||||
client.DeleteAsync($"storage/{Uri.EscapeDataString(storage)}").GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -221,7 +221,7 @@ namespace PSProxmoxVE.Core.Services
|
||||
if (string.IsNullOrWhiteSpace(storage)) throw new ArgumentNullException(nameof(storage));
|
||||
|
||||
using var client = new PveHttpClient(session);
|
||||
var response = client.GetAsync($"nodes/{node}/storage/{storage}/status").GetAwaiter().GetResult();
|
||||
var response = client.GetAsync($"nodes/{Uri.EscapeDataString(node)}/storage/{Uri.EscapeDataString(storage)}/status").GetAwaiter().GetResult();
|
||||
var data = JObject.Parse(response)["data"];
|
||||
return data?.ToObject<PveStorageStatus>() ?? new PveStorageStatus();
|
||||
}
|
||||
@@ -241,7 +241,7 @@ namespace PSProxmoxVE.Core.Services
|
||||
if (string.IsNullOrWhiteSpace(volume)) throw new ArgumentNullException(nameof(volume));
|
||||
|
||||
using var client = new PveHttpClient(session);
|
||||
client.DeleteAsync($"nodes/{node}/storage/{storage}/content/{Uri.EscapeDataString(volume)}")
|
||||
client.DeleteAsync($"nodes/{Uri.EscapeDataString(node)}/storage/{Uri.EscapeDataString(storage)}/content/{Uri.EscapeDataString(volume)}")
|
||||
.GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ namespace PSProxmoxVE.Core.Services
|
||||
if (config == null) throw new ArgumentNullException(nameof(config));
|
||||
|
||||
using var client = new PveHttpClient(session);
|
||||
client.PutAsync($"nodes/{node}/storage/{storage}/content/{Uri.EscapeDataString(volume)}", config)
|
||||
client.PutAsync($"nodes/{Uri.EscapeDataString(node)}/storage/{Uri.EscapeDataString(storage)}/content/{Uri.EscapeDataString(volume)}", config)
|
||||
.GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ namespace PSProxmoxVE.Core.Services
|
||||
if (config == null) throw new ArgumentNullException(nameof(config));
|
||||
|
||||
using var client = new PveHttpClient(session);
|
||||
var response = client.PostAsync($"nodes/{node}/storage/{storage}/content", config)
|
||||
var response = client.PostAsync($"nodes/{Uri.EscapeDataString(node)}/storage/{Uri.EscapeDataString(storage)}/content", config)
|
||||
.GetAwaiter().GetResult();
|
||||
return ParseTask(response, node);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user