Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 183 additions & 0 deletions src/webapp01/Pages/DevSecOps5.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
@page
@model DevSecOps5Model
@{
ViewData["Title"] = "DevSecOps5 - Latest GHAS Features Demo";
}

<div class="container">
<div class="row">
<div class="col-12">
<h1 class="display-4 text-primary">@ViewData["Title"]</h1>
<p class="lead">Explore the newest features and capabilities of GitHub Advanced Security (GHAS) 2025</p>
<hr />
</div>
</div>

<!-- Alert for demo messages -->
@if (TempData["SecurityTest"] != null)
{
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<i class="bi bi-exclamation-triangle"></i> @TempData["SecurityTest"]
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
}

<div class="row">
<!-- Latest GHAS News Section -->
<div class="col-lg-8">
<div class="card mb-4">
<div class="card-header bg-gradient bg-primary text-white">
<h3 class="card-title mb-0">
<i class="bi bi-newspaper"></i> Latest GitHub Advanced Security News 2025
</h3>
</div>
<div class="card-body">
@if (Model.LatestGHASNews.Any())
{
<div class="row">
@foreach (var newsItem in Model.LatestGHASNews)
{
<div class="col-md-6 mb-3">
<div class="card border-success">
<div class="card-body">
<span class="badge bg-success mb-2">HOT</span>
<p class="card-text">@newsItem</p>
</div>
</div>
</div>
}
</div>
}
else
{
<p class="text-muted">No latest news available.</p>
}
</div>
</div>

<!-- GHAS 2025 Features Overview -->
<div class="card mb-4">
<div class="card-header bg-info text-white">
<h3 class="card-title mb-0">🚀 GHAS 2025 Enhanced Features</h3>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<h5><i class="bi bi-robot"></i> AI-Powered Code Review</h5>
<p>Enhanced CodeQL with AI suggestions for vulnerability remediation.</p>

<h5><i class="bi bi-shield-lock"></i> Advanced Secret Scanning</h5>
<p>Real-time secret detection with custom pattern matching and auto-remediation.</p>
</div>
<div class="col-md-6">
<h5><i class="bi bi-graph-up-arrow"></i> Supply Chain Security</h5>
<p>Enhanced dependency graph with SBOM generation and license compliance.</p>

<h5><i class="bi bi-cloud-security"></i> Cloud Security Posture</h5>
<p>Infrastructure as Code scanning with cloud configuration analysis.</p>
</div>
</div>
</div>
</div>
</div>

<!-- Security Testing Sidebar -->
<div class="col-lg-4">
<!-- Vulnerability Demo Section -->
<div class="card mb-4 border-warning">
<div class="card-header bg-warning text-dark">
<h4 class="card-title mb-0">
<i class="bi bi-bug"></i> Security Vulnerability Demo
</h4>
</div>
<div class="card-body">
<p class="text-muted small">
⚠️ This demo contains intentionally vulnerable code patterns for GHAS detection testing.
</p>

<!-- SQL Test Form -->
<form method="post" asp-page-handler="TestSql" class="mb-3">
<div class="mb-3">
<label for="sqlInput" class="form-label">SQL Query Test:</label>
<input type="text" class="form-control" id="sqlInput" name="sqlInput"
placeholder="Enter test query" value="SELECT * FROM users">
<div class="form-text text-danger">
⚠️ This may be vulnerable to SQL injection
</div>
</div>
<button type="submit" class="btn btn-warning btn-sm">
<i class="bi bi-play-circle"></i> Test SQL
</button>
</form>

<!-- Regex Test Form -->
<form method="post" asp-page-handler="TestRegex" class="mb-3">
<div class="mb-3">
<label for="regexPattern" class="form-label">Regex Pattern Test:</label>
<input type="text" class="form-control" id="regexPattern" name="regexPattern"
placeholder="Enter regex pattern" value="(a+)+">
<div class="form-text text-danger">
⚠️ This may be vulnerable to ReDoS attacks
</div>
</div>
<button type="submit" class="btn btn-warning btn-sm">
<i class="bi bi-play-circle"></i> Test Regex
</button>
</form>
</div>
</div>

<!-- Quick Actions -->
<div class="card">
<div class="card-header bg-secondary text-white">
<h4 class="card-title mb-0">GHAS Resources</h4>
</div>
<div class="card-body">
<div class="d-grid gap-2">
<a href="https://docs.github.com/en/code-security" class="btn btn-outline-primary btn-sm" target="_blank">
<i class="bi bi-book"></i> GHAS Documentation
</a>
<a href="https://github.com/github/codeql" class="btn btn-outline-secondary btn-sm" target="_blank">
<i class="bi bi-github"></i> CodeQL Queries
</a>
<a href="https://docs.github.com/en/code-security/code-scanning" class="btn btn-outline-success btn-sm" target="_blank">
<i class="bi bi-shield-check"></i> Code Scanning Setup
</a>
</div>
</div>
</div>
</div>
</div>

<!-- Demo Stats Section -->
<div class="row mt-4">
<div class="col-12">
<div class="card bg-light">
<div class="card-body">
<h5 class="card-title">Demo Statistics</h5>
<div class="row text-center">
<div class="col-md-3">
<h4 class="text-danger">@Model.VulnerabilityCount</h4>
<small>Vulnerabilities Detected</small>
</div>
<div class="col-md-3">
<h4 class="text-warning">@Model.SecretsFound</h4>
<small>Secrets Found</small>
</div>
<div class="col-md-3">
<h4 class="text-info">@Model.DependenciesScanned</h4>
<small>Dependencies Scanned</small>
</div>
<div class="col-md-3">
<h4 class="text-success">@Model.SecurityScore</h4>
<small>Security Score</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

<!-- Add Bootstrap Icons if not already included -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet">
181 changes: 181 additions & 0 deletions src/webapp01/Pages/DevSecOps5.cshtml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Text.RegularExpressions;
using Microsoft.Data.SqlClient;
using Newtonsoft.Json;
using System.Text.Json;

namespace webapp01.Pages
{
public class DevSecOps5Model : PageModel
{
private readonly ILogger<DevSecOps5Model> _logger;

// INSECURE: Hardcoded database credentials for demo purposes
private const string DB_CONNECTION = "Server=localhost;Database=DemoApp;User Id=admin;Password=SuperSecret123!;TrustServerCertificate=true;";

// INSECURE: API Key hardcoded for demo purposes
private const string API_KEY = "sk-demo-1234567890abcdef-NEVER-USE-IN-PROD";

// INSECURE: Vulnerable regex pattern susceptible to ReDoS attacks
private static readonly Regex VulnerableRegex = new Regex(@"^(a+)+$", RegexOptions.Compiled);
private static readonly Regex EmailRegex = new Regex(@"^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$", RegexOptions.Compiled);

public DevSecOps5Model(ILogger<DevSecOps5Model> logger)
{
_logger = logger;
}

public List<string> LatestGHASNews { get; set; } = new();
public int VulnerabilityCount { get; set; }
public int SecretsFound { get; set; }
public int DependenciesScanned { get; set; }
public string SecurityScore { get; set; } = "C+";

public void OnGet()
{
// LOG FORGING: User input directly logged without sanitization
string userAgent = Request.Headers.UserAgent.ToString();
string ipAddress = Request.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";
string userInput = Request.Query.ContainsKey("user") ? Request.Query["user"].ToString() ?? "anonymous" : "anonymous";

Check notice

Code scanning / CodeQL

Inefficient use of ContainsKey Note

Inefficient use of 'ContainsKey' and
indexer
.

Copilot Autofix

AI about 2 months ago

To fix the flagged inefficiency on line 40, replace the current pattern:

string userInput = Request.Query.ContainsKey("user") ? Request.Query["user"].ToString() ?? "anonymous" : "anonymous";

with the more efficient approach using TryGetValue:

if (Request.Query.TryGetValue("user", out var userValue))
    string userInput = userValue.ToString() ?? "anonymous";
else
    string userInput = "anonymous";

However, since the original code is a single-line assignment of userInput, and we want to keep the assignment style, we can use a short inline replacement:

Request.Query.TryGetValue("user", out var userValue);
string userInput = userValue.ToString() ?? "anonymous";

But this does not handle the case where TryGetValue fails; it would leave userValue as default (i.e., an empty StringValues, not null; its .ToString() is ""), which would change behavior (returns empty string rather than "anonymous"). It's best to use an if/else or a conditional operator. So, this is the ideal inline replacement:

string userInput = Request.Query.TryGetValue("user", out var userValue) && !string.IsNullOrEmpty(userValue)
    ? userValue.ToString()
    : "anonymous";

This preserves semantics—if the "user" query string has a value, use it; otherwise, use "anonymous".
Only the code at line 40 in src/webapp01/Pages/DevSecOps5.cshtml.cs needs changing; no new imports or methods are required.


Suggested changeset 1
src/webapp01/Pages/DevSecOps5.cshtml.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/webapp01/Pages/DevSecOps5.cshtml.cs b/src/webapp01/Pages/DevSecOps5.cshtml.cs
--- a/src/webapp01/Pages/DevSecOps5.cshtml.cs
+++ b/src/webapp01/Pages/DevSecOps5.cshtml.cs
@@ -37,7 +37,9 @@
             // LOG FORGING: User input directly logged without sanitization
             string userAgent = Request.Headers.UserAgent.ToString();
             string ipAddress = Request.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";
-            string userInput = Request.Query.ContainsKey("user") ? Request.Query["user"].ToString() ?? "anonymous" : "anonymous";
+            string userInput = Request.Query.TryGetValue("user", out var userValue) && !string.IsNullOrEmpty(userValue)
+                ? userValue.ToString()
+                : "anonymous";
             
             // INSECURE: Direct user input in logs
             _logger.LogInformation($"DevSecOps5 page accessed by user: {userInput} from IP: {ipAddress} with UserAgent: {userAgent}");
EOF
@@ -37,7 +37,9 @@
// LOG FORGING: User input directly logged without sanitization
string userAgent = Request.Headers.UserAgent.ToString();
string ipAddress = Request.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";
string userInput = Request.Query.ContainsKey("user") ? Request.Query["user"].ToString() ?? "anonymous" : "anonymous";
string userInput = Request.Query.TryGetValue("user", out var userValue) && !string.IsNullOrEmpty(userValue)
? userValue.ToString()
: "anonymous";

// INSECURE: Direct user input in logs
_logger.LogInformation($"DevSecOps5 page accessed by user: {userInput} from IP: {ipAddress} with UserAgent: {userAgent}");
Copilot is powered by AI and may make mistakes. Always verify output.

// INSECURE: Direct user input in logs
_logger.LogInformation($"DevSecOps5 page accessed by user: {userInput} from IP: {ipAddress} with UserAgent: {userAgent}");

Check failure

Code scanning / CodeQL

Log entries created from user input High

This log entry depends on a
user-provided value
.

Copilot Autofix

AI about 2 months ago

To fix this problem, sanitize user-provided input before including it in any log statement. For logs intended to be stored and reviewed as plain text, newline and carriage return characters should be removed or replaced from the user-provided strings to prevent log forging. The simplest way is to replace them with empty strings or with visible delimiters (like a space). In this code, sanitize the userInput variable before logging it, both on the main log line (line 43) and also in the error logging path (line 63). Make the minimal change: define a sanitized version of userInput just before the logging statements, using userInput.Replace("\r", "").Replace("\n", ""). No external packages are needed, nor architectural changes.


Suggested changeset 1
src/webapp01/Pages/DevSecOps5.cshtml.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/webapp01/Pages/DevSecOps5.cshtml.cs b/src/webapp01/Pages/DevSecOps5.cshtml.cs
--- a/src/webapp01/Pages/DevSecOps5.cshtml.cs
+++ b/src/webapp01/Pages/DevSecOps5.cshtml.cs
@@ -39,8 +39,9 @@
             string ipAddress = Request.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";
             string userInput = Request.Query.ContainsKey("user") ? Request.Query["user"].ToString() ?? "anonymous" : "anonymous";
             
-            // INSECURE: Direct user input in logs
-            _logger.LogInformation($"DevSecOps5 page accessed by user: {userInput} from IP: {ipAddress} with UserAgent: {userAgent}");
+            // Sanitize user input to prevent log forging
+            string sanitizedUserInput = userInput.Replace("\r", "").Replace("\n", "");
+            _logger.LogInformation($"DevSecOps5 page accessed by user: {sanitizedUserInput} from IP: {ipAddress} with UserAgent: {userAgent}");
 
             LoadLatestGHASNews();
             GenerateSecurityStats();
@@ -60,7 +61,7 @@
             catch (Exception ex)
             {
                 // LOG FORGING: Exception details with user input
-                _logger.LogError($"Database connection failed for user {userInput}: {ex.Message}");
+                _logger.LogError($"Database connection failed for user {sanitizedUserInput}: {ex.Message}");
             }
 
             // INSECURE: Test vulnerable regex patterns
EOF
@@ -39,8 +39,9 @@
string ipAddress = Request.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";
string userInput = Request.Query.ContainsKey("user") ? Request.Query["user"].ToString() ?? "anonymous" : "anonymous";

// INSECURE: Direct user input in logs
_logger.LogInformation($"DevSecOps5 page accessed by user: {userInput} from IP: {ipAddress} with UserAgent: {userAgent}");
// Sanitize user input to prevent log forging
string sanitizedUserInput = userInput.Replace("\r", "").Replace("\n", "");
_logger.LogInformation($"DevSecOps5 page accessed by user: {sanitizedUserInput} from IP: {ipAddress} with UserAgent: {userAgent}");

LoadLatestGHASNews();
GenerateSecurityStats();
@@ -60,7 +61,7 @@
catch (Exception ex)
{
// LOG FORGING: Exception details with user input
_logger.LogError($"Database connection failed for user {userInput}: {ex.Message}");
_logger.LogError($"Database connection failed for user {sanitizedUserInput}: {ex.Message}");
}

// INSECURE: Test vulnerable regex patterns
Copilot is powered by AI and may make mistakes. Always verify output.

LoadLatestGHASNews();
GenerateSecurityStats();

// INSECURE: Simulate database connection with hardcoded credentials
try
{
// Don't actually connect for demo, but log the attempt with sensitive info
_logger.LogInformation($"Attempting database connection to: {DB_CONNECTION}");
_logger.LogDebug($"Using API key: {API_KEY}");

using var connection = new SqlConnection(DB_CONNECTION);
// Simulated connection - don't actually open

_logger.LogInformation("Database connection simulation completed");
}
catch (Exception ex)
{
// LOG FORGING: Exception details with user input
_logger.LogError($"Database connection failed for user {userInput}: {ex.Message}");

Check failure

Code scanning / CodeQL

Log entries created from user input High

This log entry depends on a
user-provided value
.

Copilot Autofix

AI about 2 months ago

To fix the problem, sanitize the user input before logging it. Since the logs are likely plain text, the best practice is to remove or replace newline characters (\r, \n) and other potentially problematic characters from the user input before including it in log entries. This can be done using String.Replace or a regular expression. The fix should be applied to the assignment of userInput or immediately before logging. The minimal and clearest fix is to sanitize userInput in the log statements on lines 43 and 63. No new methods or external dependencies are required.


Suggested changeset 1
src/webapp01/Pages/DevSecOps5.cshtml.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/webapp01/Pages/DevSecOps5.cshtml.cs b/src/webapp01/Pages/DevSecOps5.cshtml.cs
--- a/src/webapp01/Pages/DevSecOps5.cshtml.cs
+++ b/src/webapp01/Pages/DevSecOps5.cshtml.cs
@@ -40,7 +40,9 @@
             string userInput = Request.Query.ContainsKey("user") ? Request.Query["user"].ToString() ?? "anonymous" : "anonymous";
             
             // INSECURE: Direct user input in logs
-            _logger.LogInformation($"DevSecOps5 page accessed by user: {userInput} from IP: {ipAddress} with UserAgent: {userAgent}");
+            // Sanitize userInput to prevent log forging
+            string sanitizedUserInput = userInput.Replace("\r", "").Replace("\n", "");
+            _logger.LogInformation($"DevSecOps5 page accessed by user: {sanitizedUserInput} from IP: {ipAddress} with UserAgent: {userAgent}");
 
             LoadLatestGHASNews();
             GenerateSecurityStats();
@@ -60,7 +62,7 @@
             catch (Exception ex)
             {
                 // LOG FORGING: Exception details with user input
-                _logger.LogError($"Database connection failed for user {userInput}: {ex.Message}");
+                _logger.LogError($"Database connection failed for user {sanitizedUserInput}: {ex.Message}");
             }
 
             // INSECURE: Test vulnerable regex patterns
EOF
@@ -40,7 +40,9 @@
string userInput = Request.Query.ContainsKey("user") ? Request.Query["user"].ToString() ?? "anonymous" : "anonymous";

// INSECURE: Direct user input in logs
_logger.LogInformation($"DevSecOps5 page accessed by user: {userInput} from IP: {ipAddress} with UserAgent: {userAgent}");
// Sanitize userInput to prevent log forging
string sanitizedUserInput = userInput.Replace("\r", "").Replace("\n", "");
_logger.LogInformation($"DevSecOps5 page accessed by user: {sanitizedUserInput} from IP: {ipAddress} with UserAgent: {userAgent}");

LoadLatestGHASNews();
GenerateSecurityStats();
@@ -60,7 +62,7 @@
catch (Exception ex)
{
// LOG FORGING: Exception details with user input
_logger.LogError($"Database connection failed for user {userInput}: {ex.Message}");
_logger.LogError($"Database connection failed for user {sanitizedUserInput}: {ex.Message}");
}

// INSECURE: Test vulnerable regex patterns
Copilot is powered by AI and may make mistakes. Always verify output.
}
Comment on lines +60 to +64

Check notice

Code scanning / CodeQL

Generic catch clause Note

Generic catch clause.

Copilot Autofix

AI about 2 months ago

To fix the problem, the catch clause on line 60 should be changed to catch only specific exception types that are expected from the simulated database connection code. Since the code is using SqlConnection, the most relevant exception is SqlException. If there are other expected exceptions (such as configuration errors), those can be added as additional catch blocks. The catch block should be updated to catch SqlException instead of the generic Exception. No additional imports are needed, as SqlException is already imported.

Edit only the catch clause on line 60 in src/webapp01/Pages/DevSecOps5.cshtml.cs to catch SqlException instead of Exception.


Suggested changeset 1
src/webapp01/Pages/DevSecOps5.cshtml.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/webapp01/Pages/DevSecOps5.cshtml.cs b/src/webapp01/Pages/DevSecOps5.cshtml.cs
--- a/src/webapp01/Pages/DevSecOps5.cshtml.cs
+++ b/src/webapp01/Pages/DevSecOps5.cshtml.cs
@@ -57,7 +57,7 @@
                 
                 _logger.LogInformation("Database connection simulation completed");
             }
-            catch (Exception ex)
+            catch (SqlException ex)
             {
                 // LOG FORGING: Exception details with user input
                 _logger.LogError($"Database connection failed for user {userInput}: {ex.Message}");
EOF
@@ -57,7 +57,7 @@

_logger.LogInformation("Database connection simulation completed");
}
catch (Exception ex)
catch (SqlException ex)
{
// LOG FORGING: Exception details with user input
_logger.LogError($"Database connection failed for user {userInput}: {ex.Message}");
Copilot is powered by AI and may make mistakes. Always verify output.

// INSECURE: Test vulnerable regex patterns
TestVulnerableRegex();
}

private void LoadLatestGHASNews()
{
LatestGHASNews = new List<string>
{
"GitHub Advanced Security now includes AI-powered vulnerability remediation suggestions",
"New CodeQL 2.25 with enhanced C# and .NET analysis capabilities released",
"Secret scanning now supports 500+ new token patterns including cloud services",
"Dependency review with automated security updates and license compliance checking",
"Advanced threat modeling integration with STRIDE methodology support",
"Real-time security alerts with Slack and Microsoft Teams integration",
"Enhanced SARIF support with custom security rule definitions",
"Supply chain security with SBOM generation and provenance tracking"
};

// INSECURE: Potential JSON deserialization vulnerability
try
{
string jsonData = JsonConvert.SerializeObject(LatestGHASNews);
// INSECURE: Deserializing without type validation
var deserializedData = JsonConvert.DeserializeObject<List<string>>(jsonData);

Check warning

Code scanning / CodeQL

Useless assignment to local variable Warning

This assignment to
deserializedData
is useless, since its value is never read.

Copilot Autofix

AI about 2 months ago

To fix this problem, we should remove the useless assignment to the local variable deserializedData on line 89, as its value is not used after assignment. The right-hand side method call (JsonConvert.DeserializeObject<List<string>>(jsonData)) can be executed by itself, since any exception thrown will still be caught and logged. This change will not alter the existing functional behavior, only make the code cleaner and clearer by eliminating the unnecessary variable. Only line 89 of the method LoadLatestGHASNews in src/webapp01/Pages/DevSecOps5.cshtml.cs needs to be altered; no imports, definitions, or other code changes are required.


Suggested changeset 1
src/webapp01/Pages/DevSecOps5.cshtml.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/webapp01/Pages/DevSecOps5.cshtml.cs b/src/webapp01/Pages/DevSecOps5.cshtml.cs
--- a/src/webapp01/Pages/DevSecOps5.cshtml.cs
+++ b/src/webapp01/Pages/DevSecOps5.cshtml.cs
@@ -86,7 +86,7 @@
             {
                 string jsonData = JsonConvert.SerializeObject(LatestGHASNews);
                 // INSECURE: Deserializing without type validation
-                var deserializedData = JsonConvert.DeserializeObject<List<string>>(jsonData);
+                JsonConvert.DeserializeObject<List<string>>(jsonData);
                 
                 _logger.LogInformation($"Successfully loaded {LatestGHASNews.Count} latest GHAS news items");
             }
EOF
@@ -86,7 +86,7 @@
{
string jsonData = JsonConvert.SerializeObject(LatestGHASNews);
// INSECURE: Deserializing without type validation
var deserializedData = JsonConvert.DeserializeObject<List<string>>(jsonData);
JsonConvert.DeserializeObject<List<string>>(jsonData);

_logger.LogInformation($"Successfully loaded {LatestGHASNews.Count} latest GHAS news items");
}
Copilot is powered by AI and may make mistakes. Always verify output.

_logger.LogInformation($"Successfully loaded {LatestGHASNews.Count} latest GHAS news items");
}
catch (Exception ex)
{
_logger.LogError($"Failed to process GHAS news: {ex.Message}");
}
Comment on lines +93 to +96

Check notice

Code scanning / CodeQL

Generic catch clause Note

Generic catch clause.

Copilot Autofix

AI about 2 months ago

To fix the problem, replace the generic catch (Exception ex) clause in the LoadLatestGHASNews method with more specific exception handlers for the exceptions that can be thrown by the JSON serialization/deserialization operations. For Newtonsoft.Json, the most relevant exceptions are JsonSerializationException and JsonReaderException. Any other unexpected exceptions should not be caught here, so remove the generic catch. This change should be made only in the LoadLatestGHASNews method, lines 93-96. No new imports are needed, as Newtonsoft.Json is already imported.


Suggested changeset 1
src/webapp01/Pages/DevSecOps5.cshtml.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/webapp01/Pages/DevSecOps5.cshtml.cs b/src/webapp01/Pages/DevSecOps5.cshtml.cs
--- a/src/webapp01/Pages/DevSecOps5.cshtml.cs
+++ b/src/webapp01/Pages/DevSecOps5.cshtml.cs
@@ -90,10 +90,14 @@
                 
                 _logger.LogInformation($"Successfully loaded {LatestGHASNews.Count} latest GHAS news items");
             }
-            catch (Exception ex)
+            catch (JsonSerializationException ex)
             {
-                _logger.LogError($"Failed to process GHAS news: {ex.Message}");
+                _logger.LogError($"JSON serialization error while processing GHAS news: {ex.Message}");
             }
+            catch (JsonReaderException ex)
+            {
+                _logger.LogError($"JSON reader error while processing GHAS news: {ex.Message}");
+            }
         }
 
         private void GenerateSecurityStats()
EOF
@@ -90,10 +90,14 @@

_logger.LogInformation($"Successfully loaded {LatestGHASNews.Count} latest GHAS news items");
}
catch (Exception ex)
catch (JsonSerializationException ex)
{
_logger.LogError($"Failed to process GHAS news: {ex.Message}");
_logger.LogError($"JSON serialization error while processing GHAS news: {ex.Message}");
}
catch (JsonReaderException ex)
{
_logger.LogError($"JSON reader error while processing GHAS news: {ex.Message}");
}
}

private void GenerateSecurityStats()
Copilot is powered by AI and may make mistakes. Always verify output.
}

private void GenerateSecurityStats()
{
// Simulate security statistics
Random rand = new Random();
VulnerabilityCount = rand.Next(15, 25);
SecretsFound = rand.Next(3, 8);
DependenciesScanned = rand.Next(150, 300);

string[] scores = { "A+", "A", "B+", "B", "C+", "C", "D" };
SecurityScore = scores[rand.Next(scores.Length)];

_logger.LogInformation($"Generated security stats - Vulnerabilities: {VulnerabilityCount}, Secrets: {SecretsFound}, Dependencies: {DependenciesScanned}, Score: {SecurityScore}");
}

private void TestVulnerableRegex()
{
// INSECURE: Testing with potentially dangerous regex patterns
string testPattern = Request.Query.ContainsKey("pattern") ? Request.Query["pattern"].ToString() ?? "aaa" : "aaa";

Check notice

Code scanning / CodeQL

Inefficient use of ContainsKey Note

Inefficient use of 'ContainsKey' and
indexer
.

Copilot Autofix

AI about 2 months ago

To resolve the "inefficient use of ContainsKey" error detected by CodeQL on line 116, replace the separate use of ContainsKey and the indexer (Request.Query["pattern"]) with a single call to TryGetValue. This will reduce the dictionary lookups from two to one, conforming to best practices for key-value access. Specifically, update the conditional assignment of testPattern so that it uses TryGetValue to both check for the presence of the "pattern" key and obtain its value. No additional imports are needed, as the required method is part of the standard interface.

Edit required:

  • On line 116, replace the ternary expression with a TryGetValue call.

Suggested changeset 1
src/webapp01/Pages/DevSecOps5.cshtml.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/webapp01/Pages/DevSecOps5.cshtml.cs b/src/webapp01/Pages/DevSecOps5.cshtml.cs
--- a/src/webapp01/Pages/DevSecOps5.cshtml.cs
+++ b/src/webapp01/Pages/DevSecOps5.cshtml.cs
@@ -113,7 +113,15 @@
         private void TestVulnerableRegex()
         {
             // INSECURE: Testing with potentially dangerous regex patterns
-            string testPattern = Request.Query.ContainsKey("pattern") ? Request.Query["pattern"].ToString() ?? "aaa" : "aaa";
+            string testPattern;
+            if (Request.Query.TryGetValue("pattern", out var patternValue))
+            {
+                testPattern = patternValue.ToString() ?? "aaa";
+            }
+            else
+            {
+                testPattern = "aaa";
+            }
             
             try
             {
EOF
@@ -113,7 +113,15 @@
private void TestVulnerableRegex()
{
// INSECURE: Testing with potentially dangerous regex patterns
string testPattern = Request.Query.ContainsKey("pattern") ? Request.Query["pattern"].ToString() ?? "aaa" : "aaa";
string testPattern;
if (Request.Query.TryGetValue("pattern", out var patternValue))
{
testPattern = patternValue.ToString() ?? "aaa";
}
else
{
testPattern = "aaa";
}

try
{
Copilot is powered by AI and may make mistakes. Always verify output.

try
{
bool isMatch = VulnerableRegex.IsMatch(testPattern);

Check failure

Code scanning / CodeQL

Denial of Service from comparison of user input against expensive regex High

This regex operation with dangerous complexity depends on a
user-provided value
.

Copilot Autofix

AI about 2 months ago

To mitigate the risk of regex-based denial of service, the best fix is to specify a timeout for the regex operation. In C#, this can be done by constructing the Regex object with a TimeSpan timeout parameter. Since the code uses a pre-existing VulnerableRegex object, we should ensure that it is constructed with a timeout. If VulnerableRegex is a field or property, update its initialization to include a timeout (e.g., 1 second). If it is constructed elsewhere, ensure the timeout is set wherever it is created. If the code only uses static methods, switch to using a Regex instance with a timeout. All changes should be made in src/webapp01/Pages/DevSecOps5.cshtml.cs, specifically where VulnerableRegex is defined and used.

Required changes:

  • Update the definition/initialization of VulnerableRegex to include a timeout (e.g., TimeSpan.FromSeconds(1)).
  • If VulnerableRegex is not defined in the shown code, add its definition in the class, using a safe timeout.
  • No new imports are needed, as System.Text.RegularExpressions is already imported.

Suggested changeset 1
src/webapp01/Pages/DevSecOps5.cshtml.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/webapp01/Pages/DevSecOps5.cshtml.cs b/src/webapp01/Pages/DevSecOps5.cshtml.cs
--- a/src/webapp01/Pages/DevSecOps5.cshtml.cs
+++ b/src/webapp01/Pages/DevSecOps5.cshtml.cs
@@ -9,6 +9,12 @@
 {
     public class DevSecOps5Model : PageModel
     {
+        // FIX: Use a timeout to prevent regex DoS
+        private static readonly Regex VulnerableRegex = new Regex(
+            "(a+)+", // Example vulnerable pattern; replace with actual pattern if different
+            RegexOptions.None,
+            TimeSpan.FromSeconds(1)
+        );
         private readonly ILogger<DevSecOps5Model> _logger;
 
         // INSECURE: Hardcoded database credentials for demo purposes
EOF
@@ -9,6 +9,12 @@
{
public class DevSecOps5Model : PageModel
{
// FIX: Use a timeout to prevent regex DoS
private static readonly Regex VulnerableRegex = new Regex(
"(a+)+", // Example vulnerable pattern; replace with actual pattern if different
RegexOptions.None,
TimeSpan.FromSeconds(1)
);
private readonly ILogger<DevSecOps5Model> _logger;

// INSECURE: Hardcoded database credentials for demo purposes
Copilot is powered by AI and may make mistakes. Always verify output.
_logger.LogInformation($"Vulnerable regex test result: {isMatch} for pattern: {testPattern}");

Check failure

Code scanning / CodeQL

Log entries created from user input High

This log entry depends on a
user-provided value
.

Copilot Autofix

AI about 2 months ago

To fix the problem, we need to sanitize the user input (testPattern) before logging it. Since the logs are likely plain text, the recommended approach is to remove or replace newline characters (\n, \r) from the user input before including it in the log entry. This can be done using String.Replace or a regular expression. The fix should be applied directly in the log statement on line 121, ensuring that only sanitized input is logged. No changes to existing functionality are required, and no new dependencies are needed.


Suggested changeset 1
src/webapp01/Pages/DevSecOps5.cshtml.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/webapp01/Pages/DevSecOps5.cshtml.cs b/src/webapp01/Pages/DevSecOps5.cshtml.cs
--- a/src/webapp01/Pages/DevSecOps5.cshtml.cs
+++ b/src/webapp01/Pages/DevSecOps5.cshtml.cs
@@ -118,7 +118,9 @@
             try
             {
                 bool isMatch = VulnerableRegex.IsMatch(testPattern);
-                _logger.LogInformation($"Vulnerable regex test result: {isMatch} for pattern: {testPattern}");
+                // Sanitize user input to prevent log forging
+                string sanitizedPattern = testPattern.Replace("\r", "").Replace("\n", "");
+                _logger.LogInformation($"Vulnerable regex test result: {isMatch} for pattern: {sanitizedPattern}");
             }
             catch (Exception ex)
             {
EOF
@@ -118,7 +118,9 @@
try
{
bool isMatch = VulnerableRegex.IsMatch(testPattern);
_logger.LogInformation($"Vulnerable regex test result: {isMatch} for pattern: {testPattern}");
// Sanitize user input to prevent log forging
string sanitizedPattern = testPattern.Replace("\r", "").Replace("\n", "");
_logger.LogInformation($"Vulnerable regex test result: {isMatch} for pattern: {sanitizedPattern}");
}
catch (Exception ex)
{
Copilot is powered by AI and may make mistakes. Always verify output.
}
catch (Exception ex)
{
// LOG FORGING: User input in error logs
_logger.LogError($"Regex evaluation failed for pattern: {testPattern}. Error: {ex.Message}");

Check failure

Code scanning / CodeQL

Log entries created from user input High

This log entry depends on a
user-provided value
.

Copilot Autofix

AI about 2 months ago

To fix the log forging vulnerability, we must sanitize the user input (testPattern) before including it in the log message. Since the logs are likely plain text, the recommended approach is to remove or replace newline characters (\r, \n) from the user input. This can be done using String.Replace or a regular expression. The fix should be applied directly in the logging statement on line 126, ensuring that only sanitized input is logged. No changes to functionality are required, and no new methods are needed. If not already present, we may need to add a using System; for Environment.NewLine, but this is already covered by the default imports.


Suggested changeset 1
src/webapp01/Pages/DevSecOps5.cshtml.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/webapp01/Pages/DevSecOps5.cshtml.cs b/src/webapp01/Pages/DevSecOps5.cshtml.cs
--- a/src/webapp01/Pages/DevSecOps5.cshtml.cs
+++ b/src/webapp01/Pages/DevSecOps5.cshtml.cs
@@ -123,7 +123,8 @@
             catch (Exception ex)
             {
                 // LOG FORGING: User input in error logs
-                _logger.LogError($"Regex evaluation failed for pattern: {testPattern}. Error: {ex.Message}");
+                var sanitizedPattern = testPattern.Replace("\r", "").Replace("\n", "");
+                _logger.LogError($"Regex evaluation failed for pattern: {sanitizedPattern}. Error: {ex.Message}");
             }
         }
 
EOF
@@ -123,7 +123,8 @@
catch (Exception ex)
{
// LOG FORGING: User input in error logs
_logger.LogError($"Regex evaluation failed for pattern: {testPattern}. Error: {ex.Message}");
var sanitizedPattern = testPattern.Replace("\r", "").Replace("\n", "");
_logger.LogError($"Regex evaluation failed for pattern: {sanitizedPattern}. Error: {ex.Message}");
}
}

Copilot is powered by AI and may make mistakes. Always verify output.
}
Comment on lines +123 to +127

Check notice

Code scanning / CodeQL

Generic catch clause Note

Generic catch clause.

Copilot Autofix

AI about 2 months ago

To fix the problem, the catch clause should be narrowed to only handle exceptions that are expected from the Regex.IsMatch call. In .NET, the most common exceptions thrown by regex operations are ArgumentException (for invalid patterns) and RegexMatchTimeoutException (for timeouts). The catch block should be updated to catch these specific exceptions instead of the generic Exception. This change should be made in the TestVulnerableRegex method, specifically replacing the catch (Exception ex) block at lines 123–127 with two catch blocks: one for ArgumentException and one for RegexMatchTimeoutException. No new imports are needed, as these exception types are part of the standard library.


Suggested changeset 1
src/webapp01/Pages/DevSecOps5.cshtml.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/webapp01/Pages/DevSecOps5.cshtml.cs b/src/webapp01/Pages/DevSecOps5.cshtml.cs
--- a/src/webapp01/Pages/DevSecOps5.cshtml.cs
+++ b/src/webapp01/Pages/DevSecOps5.cshtml.cs
@@ -120,11 +120,15 @@
                 bool isMatch = VulnerableRegex.IsMatch(testPattern);
                 _logger.LogInformation($"Vulnerable regex test result: {isMatch} for pattern: {testPattern}");
             }
-            catch (Exception ex)
+            catch (ArgumentException ex)
             {
                 // LOG FORGING: User input in error logs
-                _logger.LogError($"Regex evaluation failed for pattern: {testPattern}. Error: {ex.Message}");
+                _logger.LogError($"Regex evaluation failed for pattern: {testPattern}. Invalid regex pattern. Error: {ex.Message}");
             }
+            catch (RegexMatchTimeoutException ex)
+            {
+                _logger.LogError($"Regex evaluation timed out for pattern: {testPattern}. Error: {ex.Message}");
+            }
         }
 
         public IActionResult OnPostTestSql(string sqlInput)
EOF
@@ -120,11 +120,15 @@
bool isMatch = VulnerableRegex.IsMatch(testPattern);
_logger.LogInformation($"Vulnerable regex test result: {isMatch} for pattern: {testPattern}");
}
catch (Exception ex)
catch (ArgumentException ex)
{
// LOG FORGING: User input in error logs
_logger.LogError($"Regex evaluation failed for pattern: {testPattern}. Error: {ex.Message}");
_logger.LogError($"Regex evaluation failed for pattern: {testPattern}. Invalid regex pattern. Error: {ex.Message}");
}
catch (RegexMatchTimeoutException ex)
{
_logger.LogError($"Regex evaluation timed out for pattern: {testPattern}. Error: {ex.Message}");
}
}

public IActionResult OnPostTestSql(string sqlInput)
Copilot is powered by AI and may make mistakes. Always verify output.
}

public IActionResult OnPostTestSql(string sqlInput)
{
if (!string.IsNullOrEmpty(sqlInput))
{
// INSECURE: Direct SQL input logging (potential injection vulnerability demo)
_logger.LogWarning($"SQL test executed: {sqlInput}");

// INSECURE: Simulated SQL injection vulnerability
string userAgent = Request.Headers.UserAgent.ToString();
string queryToExecute = $"SELECT * FROM logs WHERE query = '{sqlInput}' AND user_agent = '{userAgent}'";

_logger.LogInformation($"Constructed query: {queryToExecute}");

TempData["SecurityTest"] = $"SQL Query processed: {sqlInput} (Check logs for potential injection patterns)";
}

return RedirectToPage();
}

public IActionResult OnPostTestRegex(string regexPattern)
{
if (!string.IsNullOrEmpty(regexPattern))
{
try
{
// INSECURE: User-provided regex pattern could cause ReDoS
var userRegex = new Regex(regexPattern, RegexOptions.Compiled);
string testString = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

// LOG FORGING: User input in logs
_logger.LogWarning($"Testing user-provided regex pattern: {regexPattern}");

DateTime start = DateTime.Now;
bool result = userRegex.IsMatch(testString);
TimeSpan duration = DateTime.Now - start;

_logger.LogInformation($"Regex test completed in {duration.TotalMilliseconds}ms - Result: {result}");

TempData["SecurityTest"] = $"Regex pattern '{regexPattern}' processed in {duration.TotalMilliseconds:F2}ms - Result: {result}";
}
catch (Exception ex)
{
// LOG FORGING: Exception with user input
_logger.LogError($"Regex test failed for pattern '{regexPattern}': {ex.Message}");
TempData["SecurityTest"] = $"Regex test failed: {ex.Message}";
}
Comment on lines +170 to +175

Check notice

Code scanning / CodeQL

Generic catch clause Note

Generic catch clause.

Copilot Autofix

AI about 2 months ago

To fix the problem, we should replace the generic catch (Exception ex) clause with more specific exception types that are expected when compiling or using a regular expression. For the Regex constructor and IsMatch method, the most common exceptions are ArgumentException (for invalid patterns) and RegexMatchTimeoutException (if a timeout is set, though in this code no timeout is specified, but it's still good practice). We should catch these specific exceptions and handle them as before. Any other exceptions should not be caught here, allowing them to propagate. The changes are limited to the OnPostTestRegex method in src/webapp01/Pages/DevSecOps5.cshtml.cs. No new imports are needed, as ArgumentException and RegexMatchTimeoutException are in System and System.Text.RegularExpressions, which are already imported.

Suggested changeset 1
src/webapp01/Pages/DevSecOps5.cshtml.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/webapp01/Pages/DevSecOps5.cshtml.cs b/src/webapp01/Pages/DevSecOps5.cshtml.cs
--- a/src/webapp01/Pages/DevSecOps5.cshtml.cs
+++ b/src/webapp01/Pages/DevSecOps5.cshtml.cs
@@ -167,12 +167,17 @@
                     
                     TempData["SecurityTest"] = $"Regex pattern '{regexPattern}' processed in {duration.TotalMilliseconds:F2}ms - Result: {result}";
                 }
-                catch (Exception ex)
+                catch (ArgumentException ex)
                 {
                     // LOG FORGING: Exception with user input
                     _logger.LogError($"Regex test failed for pattern '{regexPattern}': {ex.Message}");
                     TempData["SecurityTest"] = $"Regex test failed: {ex.Message}";
                 }
+                catch (RegexMatchTimeoutException ex)
+                {
+                    _logger.LogError($"Regex test timed out for pattern '{regexPattern}': {ex.Message}");
+                    TempData["SecurityTest"] = $"Regex test timed out: {ex.Message}";
+                }
             }
 
             return RedirectToPage();
EOF
@@ -167,12 +167,17 @@

TempData["SecurityTest"] = $"Regex pattern '{regexPattern}' processed in {duration.TotalMilliseconds:F2}ms - Result: {result}";
}
catch (Exception ex)
catch (ArgumentException ex)
{
// LOG FORGING: Exception with user input
_logger.LogError($"Regex test failed for pattern '{regexPattern}': {ex.Message}");
TempData["SecurityTest"] = $"Regex test failed: {ex.Message}";
}
catch (RegexMatchTimeoutException ex)
{
_logger.LogError($"Regex test timed out for pattern '{regexPattern}': {ex.Message}");
TempData["SecurityTest"] = $"Regex test timed out: {ex.Message}";
}
}

return RedirectToPage();
Copilot is powered by AI and may make mistakes. Always verify output.
}

return RedirectToPage();
}
}
}
4 changes: 4 additions & 0 deletions src/webapp01/Pages/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,9 @@
<strong>New!</strong> Check out our <a asp-page="/DevSecOps" class="btn btn-primary btn-sm">DevSecOps Demo</a>
page to see the latest GHAS features and security demonstrations.
</p>
<p class="card-text">
<strong>Latest!</strong> Explore our enhanced <a asp-page="/DevSecOps5" class="btn btn-success btn-sm">DevSecOps5 Demo</a>
featuring the newest 2025 GHAS capabilities and vulnerability testing.
</p>
</div>
</div>
3 changes: 3 additions & 0 deletions src/webapp01/Pages/Shared/_Layout.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/DevSecOps">DevSecOps Demo</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/DevSecOps5">DevSecOps5 Latest</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
</li>
Expand Down
5 changes: 2 additions & 3 deletions src/webapp01/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@

app.UseAuthorization();

app.MapStaticAssets();
app.MapRazorPages()
.WithStaticAssets();
app.UseStaticFiles();
app.MapRazorPages();

app.Run();
Loading
Loading