Skip to content

Conversation

sitefinitysteve
Copy link

dotnet changes:

  • Add CRITICAL security restrictions and sanitization to C# per the TS
  • Implement READONLY property on the MCP like we have in NODE

@sitefinitysteve
Copy link
Author

Hey noticed the TS\Node blocked problematic queries going through, but dotnet just let anything happen... this should copy the behaviour.

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements comprehensive security enhancements for the MSSQL MCP server, adding READONLY mode checks and extensive SQL query validation to prevent unauthorized database operations and potential security vulnerabilities.

  • Adds READONLY mode environment variable support that blocks destructive operations
  • Implements comprehensive SQL injection protection with keyword filtering and pattern detection
  • Adds a new TestConnection tool for database connectivity validation

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
Tools/Tools.cs Adds IsReadOnlyMode property that checks READONLY environment variable
Tools/UpdateData.cs Adds READONLY mode check to prevent UPDATE operations
Tools/InsertData.cs Adds READONLY mode check to prevent INSERT operations
Tools/CreateTable.cs Adds READONLY mode check to prevent CREATE TABLE operations
Tools/DropTable.cs Adds READONLY mode check to prevent DROP TABLE operations
Tools/ReadData.cs Implements comprehensive SQL validation, injection protection, and result sanitization
Tools/TestConnection.cs New tool for testing database connectivity with connection information
MssqlMcp.Tests/UnitTests.cs Adds comprehensive test coverage for READONLY mode and TestConnection functionality

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

"DELETE", "DROP", "UPDATE", "INSERT", "ALTER", "CREATE",
"TRUNCATE", "EXEC", "EXECUTE", "MERGE", "REPLACE",
"GRANT", "REVOKE", "COMMIT", "ROLLBACK", "TRANSACTION",
"BEGIN", "DECLARE", "SET", "USE", "BACKUP",
Copy link
Preview

Copilot AI Aug 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The keyword 'BEGIN' in the dangerous keywords list could prevent legitimate SELECT queries that use BEGIN...END blocks in subqueries or CTEs. Consider being more specific (e.g., 'BEGIN TRANSACTION') or handle this in the pattern validation instead.

Suggested change
"BEGIN", "DECLARE", "SET", "USE", "BACKUP",
"DECLARE", "SET", "USE", "BACKUP",

Copilot uses AI. Check for mistakes.


// Remove comments and normalize whitespace for analysis
var cleanQuery = Regex.Replace(query, @"--.*$", "", RegexOptions.Multiline) // Remove line comments
.Replace("/*", "").Replace("*/", "") // Remove block comments (simple approach)
Copy link
Preview

Copilot AI Aug 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The block comment removal using simple string replacement is flawed. It will remove '/' and '/' independently, which could break valid queries. For example, a query with '/* comment 1 / SELECT * FROM / comment 2 /' would become ' SELECT * FROM ' but remove both opening and closing markers incorrectly. Use proper regex pattern like @'/*.?*/' with RegexOptions.Singleline.

Suggested change
.Replace("/*", "").Replace("*/", "") // Remove block comments (simple approach)
;
cleanQuery = Regex.Replace(cleanQuery, @"/\*.*?\*/", "", RegexOptions.Singleline) // Remove block comments (proper approach)

Copilot uses AI. Check for mistakes.

{
return (false, $"Dangerous keyword '{keyword}' detected in query. Only SELECT operations are allowed.");
}
}
Copy link
Preview

Copilot AI Aug 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating a new Regex object for each keyword in each validation call is inefficient. Consider pre-compiling all keyword regexes as static readonly Regex[] or use a single regex pattern with alternation like @'\b(DELETE|DROP|UPDATE|...)\b'.

Copilot uses AI. Check for mistakes.

if (query.Contains("CHAR(") || query.Contains("NCHAR(") || query.Contains("ASCII("))
{
return (false, "Character conversion functions are not allowed as they may be used for obfuscation.");
}
Copy link
Preview

Copilot AI Aug 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This validation is too restrictive and could prevent legitimate queries. Functions like CHAR(), NCHAR(), and ASCII() have valid use cases in SELECT queries for data formatting and analysis. Consider allowing these functions when used in a safe context rather than blanket prohibition.

Suggested change
}

Copilot uses AI. Check for mistakes.

/// </summary>
/// <param name="data">The query result data</param>
/// <returns>Sanitized data</returns>
private List<Dictionary<string, object?>> SanitizeResult(List<Dictionary<string, object?>> data)
Copy link
Preview

Copilot AI Aug 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SanitizeResult method processes all data even when no sanitization is needed. Consider adding an early check to see if any column names contain suspicious characters before processing the entire dataset.

Copilot uses AI. Check for mistakes.

@AV25242
Copy link
Collaborator

AV25242 commented Aug 21, 2025

@sitefinitysteve thank you for the PR, copilot assisted review and has left few comments PTAL.

@sitefinitysteve
Copy link
Author

@sitefinitysteve thank you for the PR, copilot assisted review and has left few comments PTAL.

Oh cool feature!

I'll get on it once I'm back from vacation

@AV25242
Copy link
Collaborator

AV25242 commented Aug 21, 2025

@sitefinitysteve thank you for the PR, copilot assisted review and has left few comments PTAL.

Oh cool feature!

I'll get on it once I'm back from vacation

@sitefinitysteve the one thing I noticed is that the code currently looks at the readonly flag and returns which is good (second level validation), in addition to this what would be required is showing only the tools that are readonly, i.e describe table, list tables and read.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants