mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 12:42:38 +00:00
fix cve correlation service and guid validation
This commit is contained in:
@@ -1 +1 @@
|
||||
760
|
||||
762
|
||||
|
||||
+4
-3
@@ -481,8 +481,9 @@ namespace AutopilotMonitor.Functions.Services.Vulnerability
|
||||
var cveDataJson = JsonSerializer.Serialize(cacheCves, JsonOptions);
|
||||
|
||||
// Guard against exceeding Table Storage 64KB single-property limit
|
||||
// Iteratively halve until it fits (floor: 10 CVEs)
|
||||
while (cveDataJson.Length > 60_000 && cacheCves.Count > 10)
|
||||
// Azure Table Storage uses UTF-16 encoding → 64KB = 32K chars max.
|
||||
// Use 30_000 as threshold to leave headroom for entity overhead.
|
||||
while (cveDataJson.Length > 30_000 && cacheCves.Count > 10)
|
||||
{
|
||||
cacheCves = cacheCves.Take(cacheCves.Count / 2).ToList();
|
||||
cveDataJson = JsonSerializer.Serialize(cacheCves, JsonOptions);
|
||||
@@ -491,7 +492,7 @@ namespace AutopilotMonitor.Functions.Services.Vulnerability
|
||||
}
|
||||
|
||||
// Last resort: strip Criteria strings (biggest space consumer) and retry
|
||||
if (cveDataJson.Length > 60_000)
|
||||
if (cveDataJson.Length > 30_000)
|
||||
{
|
||||
foreach (var c in cacheCves)
|
||||
foreach (var v in c.AffectedVersions)
|
||||
|
||||
@@ -11,6 +11,7 @@ import { useNotifications } from "../../contexts/NotificationContext";
|
||||
import { api } from "@/lib/api";
|
||||
import { authenticatedFetch, TokenExpiredError } from "@/lib/authenticatedFetch";
|
||||
import { trackEvent } from "@/lib/appInsights";
|
||||
import { asGuidOrUndefined } from "@/lib/inputValidation";
|
||||
import { Session } from "./types";
|
||||
import { StatsCard } from "./components/StatsCards";
|
||||
import { WelcomeMessage } from "./components/WelcomeMessage";
|
||||
@@ -100,9 +101,11 @@ export default function Home() {
|
||||
const fetchSessions = async (loadMoreCursor?: string, globalTenantIdOverride?: string) => {
|
||||
try {
|
||||
// Use different endpoint based on global admin mode
|
||||
const effectiveTenantFilter = globalTenantIdOverride !== undefined ? globalTenantIdOverride : tenantIdFilter.trim();
|
||||
// Only pass tenantIdFilter as query param if it's a valid GUID (fuzzy search sets the GUID on selection)
|
||||
const rawFilter = globalTenantIdOverride !== undefined ? globalTenantIdOverride : tenantIdFilter.trim();
|
||||
const effectiveTenantFilter = asGuidOrUndefined(rawFilter);
|
||||
let endpoint = globalAdminMode
|
||||
? api.globalSessions.list(effectiveTenantFilter || undefined)
|
||||
? api.globalSessions.list(effectiveTenantFilter)
|
||||
: api.sessions.list(tenantId);
|
||||
|
||||
// Append cursor for "Load More" requests
|
||||
|
||||
@@ -3,8 +3,7 @@ import { useState, useCallback } from "react";
|
||||
import { api } from "@/lib/api";
|
||||
import { authenticatedFetch } from "@/lib/authenticatedFetch";
|
||||
import { RuleResult } from "@/types";
|
||||
|
||||
const GUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
||||
import { isGuid } from "@/lib/inputValidation";
|
||||
|
||||
export function useSessionAnalysis(
|
||||
sessionId: string,
|
||||
@@ -16,7 +15,7 @@ export function useSessionAnalysis(
|
||||
const [vulnerabilityReport, setVulnerabilityReport] = useState<unknown>(null);
|
||||
|
||||
const fetchAnalysisResults = useCallback(async (reanalyze = false) => {
|
||||
if (!sessionTenantId || !GUID_REGEX.test(sessionTenantId)) return;
|
||||
if (!sessionTenantId || !isGuid(sessionTenantId)) return;
|
||||
try {
|
||||
setLoadingAnalysis(true);
|
||||
|
||||
@@ -38,7 +37,7 @@ export function useSessionAnalysis(
|
||||
}, [sessionId, sessionTenantId, getAccessToken]);
|
||||
|
||||
const fetchVulnerabilityReport = useCallback(async (rescan = false) => {
|
||||
if (!sessionTenantId || !GUID_REGEX.test(sessionTenantId)) return;
|
||||
if (!sessionTenantId || !isGuid(sessionTenantId)) return;
|
||||
try {
|
||||
const response = await authenticatedFetch(
|
||||
api.sessions.vulnerabilityReport(sessionId, sessionTenantId, rescan || undefined),
|
||||
|
||||
@@ -33,8 +33,7 @@ import { generateUiExport, generateCsvExport, generateSessionCsvExport, generate
|
||||
import { Session, EnrollmentEvent, RuleResult } from "@/types";
|
||||
import { trackEvent } from "@/lib/appInsights";
|
||||
import { useAdminMode } from "@/hooks/useAdminMode";
|
||||
|
||||
const GUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
||||
import { isGuid } from "@/lib/inputValidation";
|
||||
|
||||
export default function SessionDetailPage() {
|
||||
const params = useParams();
|
||||
@@ -330,7 +329,7 @@ export default function SessionDetailPage() {
|
||||
return;
|
||||
}
|
||||
const effectiveTenantId = resolveEffectiveTenantId();
|
||||
if (!effectiveTenantId || !GUID_REGEX.test(effectiveTenantId)) {
|
||||
if (!effectiveTenantId || !isGuid(effectiveTenantId)) {
|
||||
return;
|
||||
}
|
||||
fetchEventsInFlight.current = true;
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Centralised input-validation helpers.
|
||||
*
|
||||
* Every value that reaches an API call or is interpolated into a URL must
|
||||
* pass through one of these guards first. Keep validators here so pages
|
||||
* don't roll their own regex and we have a single place to harden.
|
||||
*/
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// GUID / UUID
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const GUID_RE =
|
||||
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
|
||||
/** Returns `true` when `value` is a well-formed GUID / UUID (any version). */
|
||||
export function isGuid(value: string | null | undefined): boolean {
|
||||
return !!value && GUID_RE.test(value.trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the trimmed GUID if valid, otherwise `undefined`.
|
||||
* Handy for optional query-parameter slots: pass the result straight to the
|
||||
* URL builder and it will be omitted when invalid.
|
||||
*/
|
||||
export function asGuidOrUndefined(
|
||||
value: string | null | undefined,
|
||||
): string | undefined {
|
||||
if (!value) return undefined;
|
||||
const trimmed = value.trim();
|
||||
return GUID_RE.test(trimmed) ? trimmed : undefined;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Session ID (same shape as GUID today, but named separately for clarity)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export function isSessionId(value: string | null | undefined): boolean {
|
||||
return isGuid(value);
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user