feat(UI): xml validation (#8429)

This commit is contained in:
Alejandro Bailo
2025-08-04 12:09:18 +02:00
committed by GitHub
parent 96ce1461b9
commit e19ed30ac7
2 changed files with 95 additions and 3 deletions
+1
View File
@@ -9,6 +9,7 @@ All notable changes to the **Prowler UI** are documented in this file.
- Lighthouse banner [(#8259)](https://github.com/prowler-cloud/prowler/pull/8259)
- Amazon AWS S3 integration [(#8391)](https://github.com/prowler-cloud/prowler/pull/8391)
- Github provider support [(#8405)](https://github.com/prowler-cloud/prowler/pull/8405)
- XML validation for SAML metadata in the UI [(#8429)](https://github.com/prowler-cloud/prowler/pull/8429)
### 🔄 Changed
@@ -13,6 +13,96 @@ import { SnippetChip } from "@/components/ui/entities";
import { FormButtons } from "@/components/ui/form";
import { apiBaseUrl } from "@/lib";
const validateXMLContent = (
xmlContent: string,
): { isValid: boolean; error?: string } => {
try {
// Basic checks
if (!xmlContent || !xmlContent.trim()) {
return {
isValid: false,
error: "XML content is empty.",
};
}
const trimmedContent = xmlContent.trim();
// Check if it starts and ends with XML tags
if (!trimmedContent.startsWith("<") || !trimmedContent.endsWith(">")) {
return {
isValid: false,
error: "Content does not appear to be valid XML format.",
};
}
// Use DOMParser to validate XML structure
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlContent, "text/xml");
// Check for parser errors
const parserError = xmlDoc.querySelector("parsererror");
if (parserError) {
const errorText = parserError.textContent || "Unknown XML parsing error";
return {
isValid: false,
error: `XML parsing error: ${errorText.substring(0, 100)}...`,
};
}
// Check if the document has a root element
if (!xmlDoc.documentElement) {
return {
isValid: false,
error: "XML does not have a valid root element.",
};
}
// Optional: Check for basic SAML metadata structure
const rootElement = xmlDoc.documentElement;
const rootTagName = rootElement.tagName.toLowerCase();
// Check if it looks like SAML metadata (common root elements)
const samlRootElements = [
"entitydescriptor",
"entitiesDescriptor",
"metadata",
"md:entitydescriptor",
"md:entitiesdescriptor",
];
const isSamlMetadata = samlRootElements.some((element) =>
rootTagName.includes(element.toLowerCase()),
);
if (!isSamlMetadata) {
// Check for common SAML namespace attributes
const xmlString = xmlContent.toLowerCase();
const hasSamlNamespace =
xmlString.includes("saml") ||
xmlString.includes("urn:oasis:names:tc:saml") ||
xmlString.includes("metadata");
if (!hasSamlNamespace) {
return {
isValid: false,
error:
"The XML file does not appear to be SAML metadata. Please ensure you're uploading the correct SAML metadata file from your Identity Provider.",
};
}
}
return { isValid: true };
} catch (error) {
return {
isValid: false,
error:
error instanceof Error
? error.message
: "Failed to validate XML content.",
};
}
};
export const SamlConfigForm = ({
setIsOpen,
samlConfig,
@@ -109,12 +199,13 @@ export const SamlConfigForm = ({
reader.onload = (e) => {
const content = e.target?.result as string;
// Basic XML validation
if (!content.trim().startsWith("<") || !content.includes("</")) {
// Comprehensive XML validation
const xmlValidationResult = validateXMLContent(content);
if (!xmlValidationResult.isValid) {
toast({
variant: "destructive",
title: "Invalid XML content",
description: "The file does not contain valid XML content.",
description: xmlValidationResult.error,
});
// Clear the file input
event.target.value = "";