mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 12:42:38 +00:00
Security: request size limit, symlink detection
This commit is contained in:
@@ -106,6 +106,10 @@ namespace AutopilotMonitor.Agent.Core.Monitoring.Collectors
|
||||
normalizedDir = Path.GetFullPath(expanded);
|
||||
}
|
||||
|
||||
// Symlink / junction / reparse point detection — fail-closed
|
||||
if (IsSymlinkOrReparsePoint(normalizedDir))
|
||||
return false;
|
||||
|
||||
// C:\Users block always applies (even in unrestricted mode)
|
||||
if (normalizedDir.StartsWith(BlockedUsersPrefix, StringComparison.OrdinalIgnoreCase) &&
|
||||
(normalizedDir.Length == BlockedUsersPrefix.Length ||
|
||||
@@ -152,5 +156,45 @@ namespace AutopilotMonitor.Agent.Core.Monitoring.Collectors
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether any component of the path (directories or file) is a symlink,
|
||||
/// junction, or other reparse point. Returns true if a reparse point is detected.
|
||||
/// Fail-closed: returns true on any error.
|
||||
/// </summary>
|
||||
private static bool IsSymlinkOrReparsePoint(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Walk up the directory tree checking each component
|
||||
var current = path;
|
||||
while (!string.IsNullOrEmpty(current))
|
||||
{
|
||||
var dirInfo = new DirectoryInfo(current);
|
||||
if (dirInfo.Exists && dirInfo.Attributes.HasFlag(FileAttributes.ReparsePoint))
|
||||
return true;
|
||||
|
||||
var parent = Path.GetDirectoryName(current);
|
||||
if (parent == current) // root reached
|
||||
break;
|
||||
current = parent;
|
||||
}
|
||||
|
||||
// Check the target path itself (if it's a file)
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var fileInfo = new FileInfo(path);
|
||||
if (fileInfo.Attributes.HasFlag(FileAttributes.ReparsePoint))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Fail-closed: treat errors as suspicious
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
580
|
||||
581
|
||||
|
||||
@@ -135,6 +135,16 @@ namespace AutopilotMonitor.Functions.Functions.Feedback
|
||||
var principal = req.FunctionContext.GetUser();
|
||||
string displayName = principal?.GetDisplayName() ?? upn;
|
||||
|
||||
// Request body size limit (1 MB)
|
||||
if (req.Headers.TryGetValues("Content-Length", out var clValues)
|
||||
&& long.TryParse(clValues.FirstOrDefault(), out var contentLength)
|
||||
&& contentLength > 1_048_576)
|
||||
{
|
||||
var tooLarge = req.CreateResponse(HttpStatusCode.BadRequest);
|
||||
await tooLarge.WriteAsJsonAsync(new { success = false, message = "Request body too large" });
|
||||
return tooLarge;
|
||||
}
|
||||
|
||||
var body = await req.ReadFromJsonAsync<FeedbackRequest>();
|
||||
if (body == null)
|
||||
{
|
||||
|
||||
@@ -101,6 +101,15 @@ namespace AutopilotMonitor.Functions.Functions.Ingest
|
||||
/// </summary>
|
||||
internal async Task<HttpResponseData> ProcessReportErrorAsync(HttpRequestData req, string tenantId)
|
||||
{
|
||||
// Request body size limit (1 MB)
|
||||
if (req.Headers.TryGetValues("Content-Length", out var clValues)
|
||||
&& long.TryParse(clValues.FirstOrDefault(), out var contentLength)
|
||||
&& contentLength > 1_048_576)
|
||||
{
|
||||
_logger.LogWarning("ReportAgentError: Request body too large ({ContentLength} bytes) from tenant {TenantId}", contentLength, tenantId);
|
||||
return req.CreateResponse(HttpStatusCode.OK); // Still 200 — agent must not retry
|
||||
}
|
||||
|
||||
// Parse the report body
|
||||
AgentErrorReport? report = null;
|
||||
try
|
||||
|
||||
+10
@@ -49,6 +49,16 @@ namespace AutopilotMonitor.Functions.Functions.Reports
|
||||
// Still needed: GA check for audit log skip logic
|
||||
var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(userIdentifier);
|
||||
|
||||
// Request body size limit (1 MB)
|
||||
if (req.Headers.TryGetValues("Content-Length", out var clValues)
|
||||
&& long.TryParse(clValues.FirstOrDefault(), out var contentLength)
|
||||
&& contentLength > 1_048_576)
|
||||
{
|
||||
var tooLarge = req.CreateResponse(HttpStatusCode.BadRequest);
|
||||
await tooLarge.WriteAsJsonAsync(new { success = false, message = "Request body too large" });
|
||||
return tooLarge;
|
||||
}
|
||||
|
||||
// Parse request body
|
||||
var request = await req.ReadFromJsonAsync<SubmitSessionReportRequest>();
|
||||
if (request == null)
|
||||
|
||||
Reference in New Issue
Block a user