diff --git a/.gitignore b/.gitignore index 52c1b1e8..152183fd 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,5 @@ packages/ *.userosscache *.sln.docstates +# Python +Scripts/venv/ \ No newline at end of file diff --git a/Contentstack.Core.Tests/Contentstack.Core.Tests.csproj b/Contentstack.Core.Tests/Contentstack.Core.Tests.csproj index 42960a42..85968f71 100644 --- a/Contentstack.Core.Tests/Contentstack.Core.Tests.csproj +++ b/Contentstack.Core.Tests/Contentstack.Core.Tests.csproj @@ -1,4 +1,4 @@ - + net7.0 @@ -27,6 +27,8 @@ + + diff --git a/Contentstack.Core.Tests/Helpers/TestDataHelper.cs b/Contentstack.Core.Tests/Helpers/TestDataHelper.cs index 0813ebca..9499df51 100644 --- a/Contentstack.Core.Tests/Helpers/TestDataHelper.cs +++ b/Contentstack.Core.Tests/Helpers/TestDataHelper.cs @@ -187,16 +187,16 @@ static TestDataHelper() /// /// Gets a required configuration value and throws if not found /// - /// Configuration key + /// Configuration key name /// Configuration value /// Thrown when configuration is missing - private static string GetRequiredConfig(string key) + private static string GetRequiredConfig(string configKey) { - var value = ConfigurationManager.AppSettings[key]; + var value = ConfigurationManager.AppSettings[configKey]; if (string.IsNullOrEmpty(value)) { throw new InvalidOperationException( - $"Required configuration '{key}' is missing from app.config. " + + $"Required configuration '{configKey}' is missing from app.config. " + $"Please ensure all required keys are present in the section."); } return value; @@ -205,12 +205,12 @@ private static string GetRequiredConfig(string key) /// /// Gets an optional configuration value with a default /// - /// Configuration key + /// Configuration key name /// Default value if not found /// Configuration value or default - private static string GetOptionalConfig(string key, string defaultValue = null) + private static string GetOptionalConfig(string configKey, string defaultValue = null) { - return ConfigurationManager.AppSettings[key] ?? defaultValue; + return ConfigurationManager.AppSettings[configKey] ?? defaultValue; } /// diff --git a/Contentstack.Core.Unit.Tests/Contentstack.Core.Unit.Tests.csproj b/Contentstack.Core.Unit.Tests/Contentstack.Core.Unit.Tests.csproj index bb1056f5..a4138b9d 100644 --- a/Contentstack.Core.Unit.Tests/Contentstack.Core.Unit.Tests.csproj +++ b/Contentstack.Core.Unit.Tests/Contentstack.Core.Unit.Tests.csproj @@ -18,6 +18,8 @@ + + diff --git a/Scripts/generate_enhanced_html_report.py b/Scripts/generate_enhanced_html_report.py index 8367b648..d8a3e7d1 100644 --- a/Scripts/generate_enhanced_html_report.py +++ b/Scripts/generate_enhanced_html_report.py @@ -5,10 +5,10 @@ - Expected vs Actual values - HTTP Request details (including cURL) - Response details -No external dependencies - uses only Python standard library +Uses defusedxml for secure XML parsing (XXE/DDoS-safe). """ -import xml.etree.ElementTree as ET +import defusedxml.ElementTree as ET import os import sys import re @@ -158,9 +158,9 @@ def parse_trx(self): test_output = stdout_elem.text structured_output = self.parse_structured_output(test_output) - # Get test category + # Get test category (find by id without dynamic XPath to avoid CWE-643) test_def_id = test_result.get('testId', '') - test_def = root.find(f".//UnitTest[@id='{test_def_id}']", ns) + test_def = next((el for el in root.findall('.//UnitTest', ns) if el.get('id') == test_def_id), None) category = 'General' if test_def is not None: test_method = test_def.find('.//TestMethod', ns) diff --git a/Scripts/generate_html_report.py b/Scripts/generate_html_report.py index ca84a439..de116b13 100644 --- a/Scripts/generate_html_report.py +++ b/Scripts/generate_html_report.py @@ -1,11 +1,11 @@ #!/usr/bin/env python3 """ HTML Test Report Generator for .NET Test Results -Converts .trx files to beautiful HTML reports -No external dependencies - uses only Python standard library +Converts .trx files to beautiful HTML reports. +Uses defusedxml for secure XML parsing (XXE/DDoS-safe). """ -import xml.etree.ElementTree as ET +import defusedxml.ElementTree as ET import os import sys from datetime import datetime @@ -78,9 +78,9 @@ def parse_trx(self): if stacktrace_elem is not None: error_stacktrace = stacktrace_elem.text - # Get test category + # Get test category (find by id without dynamic XPath to avoid CWE-643) test_def_id = test_result.get('testId', '') - test_def = root.find(f".//UnitTest[@id='{test_def_id}']", ns) + test_def = next((el for el in root.findall('.//UnitTest', ns) if el.get('id') == test_def_id), None) category = 'General' if test_def is not None: test_method = test_def.find('.//TestMethod', ns) diff --git a/Scripts/requirements.txt b/Scripts/requirements.txt new file mode 100644 index 00000000..377b0d3e --- /dev/null +++ b/Scripts/requirements.txt @@ -0,0 +1,2 @@ +# Secure XML parsing (fixes Snyk CWE-611 Insecure Xml Parser / XXE) +defusedxml>=0.7.1