diff --git a/SECURITY_SUMMARY.md b/SECURITY_SUMMARY.md
new file mode 100644
index 0000000..d33fac2
--- /dev/null
+++ b/SECURITY_SUMMARY.md
@@ -0,0 +1,203 @@
+# Security Summary - SafeVault Project
+
+## Overview
+This document outlines the security vulnerabilities that were identified during development and the fixes that were applied to the SafeVault application.
+
+## Activity 1: Secure Coding Practices
+
+### Vulnerability 1: Cross-Site Scripting (XSS)
+**Description:** User input could contain malicious JavaScript code that executes in the browser.
+
+**Example Attack:**
+```html
+
+
+```
+
+**Fix Applied:**
+- Implemented `InputSanitizer.SanitizeForXss()` method
+- Encodes HTML special characters: `<`, `>`, `&`, `"`, `'`, `/`
+- All user inputs displayed in HTML context are sanitized
+- Applied in webform.html with proper validation
+
+**Location:** `SafeVault.App/Security/InputSanitizer.cs`
+
+### Vulnerability 2: SQL Injection
+**Description:** Unparameterized SQL queries could allow attackers to manipulate database queries.
+
+**Example Attack:**
+```sql
+Username: admin' OR '1'='1
+Password: anything' OR '1'='1
+```
+
+**Fix Applied:**
+- Implemented parameterized queries in `UserRepository`
+- All SQL queries use parameter binding via `DbCommand.Parameters`
+- Added `InputSanitizer.ContainsSqlInjectionPattern()` to detect injection attempts
+- Input validation prevents malicious patterns from reaching the database
+
+**Vulnerable Code (DO NOT USE):**
+```csharp
+// INSECURE - String concatenation
+string query = "SELECT * FROM Users WHERE Username = '" + username + "'";
+```
+
+**Secure Code (USED):**
+```csharp
+// SECURE - Parameterized query
+string query = "SELECT * FROM Users WHERE Username = @Username";
+command.Parameters.Add(new SqlParameter("@Username", username));
+```
+
+**Location:** `SafeVault.App/Data/UserRepository.cs`
+
+### Vulnerability 3: Weak Input Validation
+**Description:** Insufficient validation could allow malformed or malicious data.
+
+**Fix Applied:**
+- Email validation using regex pattern
+- Username validation (alphanumeric + underscore, 3-20 characters)
+- SQL injection pattern detection
+- Password strength requirements enforced
+
+**Location:** `SafeVault.App/Security/InputSanitizer.cs`
+
+## Activity 2: Authentication & Authorization
+
+### Vulnerability 4: Plain Text Passwords
+**Description:** Storing passwords in plain text or using weak hashing exposes user credentials.
+
+**Fix Applied:**
+- Implemented BCrypt password hashing with work factor
+- Uses `AuthService.HashPassword()` for password hashing
+- Uses `AuthService.VerifyPassword()` for secure password verification
+- BCrypt automatically handles salting and multiple rounds of hashing
+
+**Vulnerable Code (DO NOT USE):**
+```csharp
+// INSECURE - Plain text or simple hash
+user.Password = password; // Plain text
+user.PasswordHash = ComputeSHA256(password); // Weak hash without salt
+```
+
+**Secure Code (USED):**
+```csharp
+// SECURE - BCrypt with automatic salting
+user.PasswordHash = AuthService.HashPassword(password);
+bool isValid = AuthService.VerifyPassword(password, user.PasswordHash);
+```
+
+**Location:** `SafeVault.App/Security/AuthService.cs`
+
+### Vulnerability 5: Missing Authorization Checks
+**Description:** Users could access resources or perform actions without proper authorization.
+
+**Fix Applied:**
+- Implemented role-based authorization with `RoleAuthorization`
+- Admin and User roles defined
+- `RequireAdmin()` and `RequireRole()` methods enforce authorization
+- `CanAccessResource()` checks resource ownership
+- Throws `UnauthorizedAccessException` for unauthorized access attempts
+
+**Location:** `SafeVault.App/Security/RoleAuthorization.cs`
+
+### Vulnerability 6: Weak Password Requirements
+**Description:** Weak passwords could be easily guessed or brute-forced.
+
+**Fix Applied:**
+- Password must be at least 8 characters
+- Must contain uppercase letter
+- Must contain lowercase letter
+- Must contain digit
+- Must contain special character
+- Validated by `AuthService.IsStrongPassword()`
+
+**Location:** `SafeVault.App/Security/AuthService.cs`
+
+## Activity 3: Security Testing & Regression Prevention
+
+### Security Testing Implementation
+To prevent regression of security vulnerabilities, comprehensive tests were implemented:
+
+1. **TestInputValidation.cs**
+ - Tests XSS sanitization
+ - Tests SQL injection detection
+ - Tests email validation
+ - Tests username validation
+
+2. **TestAuthentication.cs**
+ - Tests password hashing
+ - Tests password verification
+ - Tests login with valid/invalid credentials
+ - Tests password strength requirements
+
+3. **TestAuthorization.cs**
+ - Tests role checking (admin/user)
+ - Tests resource access control
+ - Tests authorization exceptions
+ - Tests privilege escalation prevention
+
+4. **TestSecurityRegression.cs**
+ - Tests for previously vulnerable patterns
+ - Tests parameterized query usage
+ - Tests input sanitization consistency
+ - Ensures security fixes remain effective
+
+**Location:** `Tests/` folder
+
+## Security Best Practices Applied
+
+### 1. Defense in Depth
+- Multiple layers of security: input validation, sanitization, parameterized queries
+- Client-side and server-side validation
+- Both preventive (parameterized queries) and detective (pattern matching) controls
+
+### 2. Principle of Least Privilege
+- Role-based access control limits user permissions
+- Users can only access their own resources
+- Admins have elevated privileges with explicit checks
+
+### 3. Secure by Default
+- Default role is "user" (not admin)
+- All queries use parameterized approach
+- Password hashing is mandatory
+- Input validation required before database operations
+
+### 4. Security Through Obscurity Avoided
+- Security mechanisms are well-documented
+- Relies on proven cryptographic methods (BCrypt)
+- Uses industry-standard security practices
+
+## Remaining Considerations
+
+### Production Deployment Recommendations
+1. **HTTPS:** Use TLS/SSL for all communications
+2. **CSRF Protection:** Implement anti-CSRF tokens for web forms
+3. **Rate Limiting:** Prevent brute-force attacks on login
+4. **Session Management:** Implement secure session handling
+5. **Logging:** Log authentication attempts and authorization failures
+6. **Database Security:** Use database-level access controls
+7. **Secrets Management:** Store connection strings securely (not in code)
+8. **Regular Updates:** Keep BCrypt.Net-Next and other dependencies updated
+
+### Potential Future Enhancements
+- Two-factor authentication (2FA)
+- Account lockout after failed login attempts
+- Password reset functionality with secure tokens
+- Audit logging for all security-relevant events
+- Content Security Policy (CSP) headers
+- Input sanitization for additional contexts (URLs, JSON, etc.)
+
+## Testing Verification
+All security tests pass successfully:
+- ✅ Input validation tests
+- ✅ Authentication tests
+- ✅ Authorization tests
+- ✅ Security regression tests
+
+## Conclusion
+The SafeVault application implements comprehensive security controls to protect against common vulnerabilities including XSS, SQL injection, weak authentication, and inadequate authorization. All identified vulnerabilities have been addressed with industry-standard security practices and are covered by automated tests to prevent regression.
+
+**Last Updated:** February 9, 2026
+**Version:** 1.0
diff --git a/SafeVault.App/Data/UserRepository.cs b/SafeVault.App/Data/UserRepository.cs
new file mode 100644
index 0000000..9b271ea
--- /dev/null
+++ b/SafeVault.App/Data/UserRepository.cs
@@ -0,0 +1,203 @@
+using System.Data;
+using System.Data.Common;
+using SafeVault.App.Models;
+using SafeVault.App.Security;
+
+namespace SafeVault.App.Data;
+
+///
+/// Repository for User data access using parameterized SQL queries to prevent SQL injection
+///
+public class UserRepository
+{
+ private readonly DbConnection _connection;
+
+ public UserRepository(DbConnection connection)
+ {
+ _connection = connection ?? throw new ArgumentNullException(nameof(connection));
+ }
+
+ ///
+ /// Creates a new user with sanitized input and parameterized query
+ ///
+ public int CreateUser(string username, string email, string password, string role = "user")
+ {
+ // Validate and sanitize inputs
+ if (!InputSanitizer.IsValidUsername(username))
+ throw new ArgumentException("Invalid username format", nameof(username));
+
+ if (!InputSanitizer.IsValidEmail(email))
+ throw new ArgumentException("Invalid email format", nameof(email));
+
+ if (!AuthService.IsStrongPassword(password))
+ throw new ArgumentException("Password does not meet security requirements", nameof(password));
+
+ // Hash password
+ string passwordHash = AuthService.HashPassword(password);
+
+ // Use parameterized query to prevent SQL injection
+ string query = @"
+ INSERT INTO Users (Username, Email, PasswordHash, Role)
+ VALUES (@Username, @Email, @PasswordHash, @Role);
+ SELECT last_insert_rowid();";
+
+ using var command = _connection.CreateCommand();
+ command.CommandText = query;
+
+ AddParameter(command, "@Username", username);
+ AddParameter(command, "@Email", email);
+ AddParameter(command, "@PasswordHash", passwordHash);
+ AddParameter(command, "@Role", role);
+
+ if (_connection.State != ConnectionState.Open)
+ _connection.Open();
+
+ var result = command.ExecuteScalar();
+ return Convert.ToInt32(result);
+ }
+
+ ///
+ /// Gets a user by username using parameterized query
+ ///
+ public User? GetUserByUsername(string username)
+ {
+ if (string.IsNullOrEmpty(username))
+ return null;
+
+ // Use parameterized query to prevent SQL injection
+ string query = "SELECT Id, Username, Email, PasswordHash, Role FROM Users WHERE Username = @Username";
+
+ using var command = _connection.CreateCommand();
+ command.CommandText = query;
+ AddParameter(command, "@Username", username);
+
+ if (_connection.State != ConnectionState.Open)
+ _connection.Open();
+
+ using var reader = command.ExecuteReader();
+ if (reader.Read())
+ {
+ return new User
+ {
+ Id = reader.GetInt32(0),
+ Username = reader.GetString(1),
+ Email = reader.GetString(2),
+ PasswordHash = reader.GetString(3),
+ Role = reader.GetString(4)
+ };
+ }
+
+ return null;
+ }
+
+ ///
+ /// Gets a user by ID using parameterized query
+ ///
+ public User? GetUserById(int id)
+ {
+ // Use parameterized query to prevent SQL injection
+ string query = "SELECT Id, Username, Email, PasswordHash, Role FROM Users WHERE Id = @Id";
+
+ using var command = _connection.CreateCommand();
+ command.CommandText = query;
+ AddParameter(command, "@Id", id);
+
+ if (_connection.State != ConnectionState.Open)
+ _connection.Open();
+
+ using var reader = command.ExecuteReader();
+ if (reader.Read())
+ {
+ return new User
+ {
+ Id = reader.GetInt32(0),
+ Username = reader.GetString(1),
+ Email = reader.GetString(2),
+ PasswordHash = reader.GetString(3),
+ Role = reader.GetString(4)
+ };
+ }
+
+ return null;
+ }
+
+ ///
+ /// Updates user role using parameterized query
+ ///
+ public bool UpdateUserRole(int userId, string newRole)
+ {
+ // Use parameterized query to prevent SQL injection
+ string query = "UPDATE Users SET Role = @Role WHERE Id = @Id";
+
+ using var command = _connection.CreateCommand();
+ command.CommandText = query;
+ AddParameter(command, "@Role", newRole);
+ AddParameter(command, "@Id", userId);
+
+ if (_connection.State != ConnectionState.Open)
+ _connection.Open();
+
+ int rowsAffected = command.ExecuteNonQuery();
+ return rowsAffected > 0;
+ }
+
+ ///
+ /// Deletes a user using parameterized query
+ ///
+ public bool DeleteUser(int userId)
+ {
+ // Use parameterized query to prevent SQL injection
+ string query = "DELETE FROM Users WHERE Id = @Id";
+
+ using var command = _connection.CreateCommand();
+ command.CommandText = query;
+ AddParameter(command, "@Id", userId);
+
+ if (_connection.State != ConnectionState.Open)
+ _connection.Open();
+
+ int rowsAffected = command.ExecuteNonQuery();
+ return rowsAffected > 0;
+ }
+
+ ///
+ /// Gets all users using secure query
+ ///
+ public List GetAllUsers()
+ {
+ var users = new List();
+ string query = "SELECT Id, Username, Email, PasswordHash, Role FROM Users";
+
+ using var command = _connection.CreateCommand();
+ command.CommandText = query;
+
+ if (_connection.State != ConnectionState.Open)
+ _connection.Open();
+
+ using var reader = command.ExecuteReader();
+ while (reader.Read())
+ {
+ users.Add(new User
+ {
+ Id = reader.GetInt32(0),
+ Username = reader.GetString(1),
+ Email = reader.GetString(2),
+ PasswordHash = reader.GetString(3),
+ Role = reader.GetString(4)
+ });
+ }
+
+ return users;
+ }
+
+ ///
+ /// Helper method to add parameters safely
+ ///
+ private void AddParameter(DbCommand command, string parameterName, object value)
+ {
+ var parameter = command.CreateParameter();
+ parameter.ParameterName = parameterName;
+ parameter.Value = value ?? DBNull.Value;
+ command.Parameters.Add(parameter);
+ }
+}
diff --git a/SafeVault.App/Models/User.cs b/SafeVault.App/Models/User.cs
new file mode 100644
index 0000000..a5a5979
--- /dev/null
+++ b/SafeVault.App/Models/User.cs
@@ -0,0 +1,10 @@
+namespace SafeVault.App.Models;
+
+public class User
+{
+ public int Id { get; set; }
+ public string Username { get; set; } = string.Empty;
+ public string Email { get; set; } = string.Empty;
+ public string PasswordHash { get; set; } = string.Empty;
+ public string Role { get; set; } = "user";
+}
diff --git a/SafeVault.App/Program.cs b/SafeVault.App/Program.cs
new file mode 100644
index 0000000..e05beda
--- /dev/null
+++ b/SafeVault.App/Program.cs
@@ -0,0 +1,139 @@
+using SafeVault.App.Models;
+using SafeVault.App.Security;
+
+namespace SafeVault.App;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ Console.WriteLine("=== SafeVault - Secure Authentication & Authorization Demo ===\n");
+
+ // Demo users list (in real app, this would be a database)
+ var users = new List();
+
+ // Activity 1: Input Sanitization Demo
+ Console.WriteLine("--- Activity 1: Input Sanitization ---");
+ DemoInputSanitization();
+
+ // Activity 2: Authentication Demo
+ Console.WriteLine("\n--- Activity 2: Authentication ---");
+ var admin = DemoAuthentication(users);
+
+ // Activity 2: Authorization Demo
+ Console.WriteLine("\n--- Activity 2: Authorization ---");
+ DemoAuthorization(admin, users);
+
+ Console.WriteLine("\n=== Demo Complete ===");
+ }
+
+ static void DemoInputSanitization()
+ {
+ // XSS Protection
+ string maliciousInput = "";
+ string sanitized = InputSanitizer.SanitizeForXss(maliciousInput);
+ Console.WriteLine($"Original: {maliciousInput}");
+ Console.WriteLine($"Sanitized: {sanitized}");
+
+ // SQL Injection Detection
+ string sqlInjection = "admin' OR '1'='1";
+ bool isSqlInjection = InputSanitizer.ContainsSqlInjectionPattern(sqlInjection);
+ Console.WriteLine($"\nInput: {sqlInjection}");
+ Console.WriteLine($"Contains SQL Injection Pattern: {isSqlInjection}");
+
+ // Email Validation
+ string validEmail = "user@example.com";
+ string invalidEmail = "not-an-email";
+ Console.WriteLine($"\n'{validEmail}' is valid email: {InputSanitizer.IsValidEmail(validEmail)}");
+ Console.WriteLine($"'{invalidEmail}' is valid email: {InputSanitizer.IsValidEmail(invalidEmail)}");
+
+ // Username Validation
+ string validUsername = "john_doe123";
+ string invalidUsername = "john@doe";
+ Console.WriteLine($"\n'{validUsername}' is valid username: {InputSanitizer.IsValidUsername(validUsername)}");
+ Console.WriteLine($"'{invalidUsername}' is valid username: {InputSanitizer.IsValidUsername(invalidUsername)}");
+ }
+
+ static User DemoAuthentication(List users)
+ {
+ // Create an admin user
+ string password = "SecurePass123!";
+ string passwordHash = AuthService.HashPassword(password);
+
+ var admin = new User
+ {
+ Id = 1,
+ Username = "admin",
+ Email = "admin@safevault.com",
+ PasswordHash = passwordHash,
+ Role = "admin"
+ };
+ users.Add(admin);
+
+ Console.WriteLine("Created admin user with hashed password");
+ Console.WriteLine($"Password: {password}");
+ Console.WriteLine($"Hash: {passwordHash.Substring(0, 20)}...");
+
+ // Test valid login
+ var loginResult = AuthService.Login("admin", password, users);
+ Console.WriteLine($"\nLogin with correct password: {(loginResult != null ? "SUCCESS" : "FAILED")}");
+
+ // Test invalid login
+ loginResult = AuthService.Login("admin", "wrongpassword", users);
+ Console.WriteLine($"Login with wrong password: {(loginResult != null ? "SUCCESS" : "FAILED")}");
+
+ // Test password strength
+ Console.WriteLine($"\nPassword strength check:");
+ Console.WriteLine($"'weak' is strong: {AuthService.IsStrongPassword("weak")}");
+ Console.WriteLine($"'SecurePass123!' is strong: {AuthService.IsStrongPassword("SecurePass123!")}");
+
+ return admin;
+ }
+
+ static void DemoAuthorization(User admin, List users)
+ {
+ // Create a regular user
+ var user = new User
+ {
+ Id = 2,
+ Username = "john_doe",
+ Email = "john@example.com",
+ PasswordHash = AuthService.HashPassword("UserPass123!"),
+ Role = "user"
+ };
+ users.Add(user);
+
+ // Check admin privileges
+ Console.WriteLine($"Admin user is admin: {RoleAuthorization.IsAdmin(admin)}");
+ Console.WriteLine($"Regular user is admin: {RoleAuthorization.IsAdmin(user)}");
+
+ // Check resource access
+ int resourceOwnerId = 2; // Resource owned by john_doe
+ Console.WriteLine($"\nResource access (Owner ID: {resourceOwnerId}):");
+ Console.WriteLine($"Admin can access: {RoleAuthorization.CanAccessResource(admin, resourceOwnerId)}");
+ Console.WriteLine($"Owner can access: {RoleAuthorization.CanAccessResource(user, resourceOwnerId)}");
+
+ // Test requiring admin role
+ try
+ {
+ Console.WriteLine("\nTrying admin-only operation with admin user...");
+ RoleAuthorization.RequireAdmin(admin);
+ Console.WriteLine("SUCCESS: Admin operation allowed");
+ }
+ catch (UnauthorizedAccessException ex)
+ {
+ Console.WriteLine($"FAILED: {ex.Message}");
+ }
+
+ try
+ {
+ Console.WriteLine("\nTrying admin-only operation with regular user...");
+ RoleAuthorization.RequireAdmin(user);
+ Console.WriteLine("SUCCESS: Admin operation allowed");
+ }
+ catch (UnauthorizedAccessException ex)
+ {
+ Console.WriteLine($"FAILED: {ex.Message}");
+ }
+ }
+}
diff --git a/SafeVault.App/SafeVault.App.csproj b/SafeVault.App/SafeVault.App.csproj
new file mode 100644
index 0000000..a858f5a
--- /dev/null
+++ b/SafeVault.App/SafeVault.App.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/SafeVault.App/Security/AuthService.cs b/SafeVault.App/Security/AuthService.cs
new file mode 100644
index 0000000..2e34cfb
--- /dev/null
+++ b/SafeVault.App/Security/AuthService.cs
@@ -0,0 +1,77 @@
+using SafeVault.App.Models;
+
+namespace SafeVault.App.Security;
+
+///
+/// Provides authentication services with secure password hashing using BCrypt
+///
+public class AuthService
+{
+ ///
+ /// Hashes a password using BCrypt
+ ///
+ public static string HashPassword(string password)
+ {
+ if (string.IsNullOrEmpty(password))
+ throw new ArgumentException("Password cannot be null or empty", nameof(password));
+
+ return BCrypt.Net.BCrypt.HashPassword(password);
+ }
+
+ ///
+ /// Verifies a password against a hash
+ ///
+ public static bool VerifyPassword(string password, string hash)
+ {
+ if (string.IsNullOrEmpty(password) || string.IsNullOrEmpty(hash))
+ return false;
+
+ try
+ {
+ return BCrypt.Net.BCrypt.Verify(password, hash);
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Authenticates a user with username and password
+ /// Returns the user if authentication is successful, null otherwise
+ ///
+ public static User? Login(string username, string password, List users)
+ {
+ if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
+ return null;
+
+ // Find user by username
+ var user = users.FirstOrDefault(u => u.Username.Equals(username, StringComparison.OrdinalIgnoreCase));
+
+ if (user == null)
+ return null;
+
+ // Verify password
+ if (!VerifyPassword(password, user.PasswordHash))
+ return null;
+
+ return user;
+ }
+
+ ///
+ /// Validates password strength
+ /// Password must be at least 8 characters with uppercase, lowercase, digit, and special character
+ ///
+ public static bool IsStrongPassword(string password)
+ {
+ if (string.IsNullOrEmpty(password) || password.Length < 8)
+ return false;
+
+ bool hasUpper = password.Any(char.IsUpper);
+ bool hasLower = password.Any(char.IsLower);
+ bool hasDigit = password.Any(char.IsDigit);
+ bool hasSpecial = password.Any(c => !char.IsLetterOrDigit(c));
+
+ return hasUpper && hasLower && hasDigit && hasSpecial;
+ }
+}
diff --git a/SafeVault.App/Security/InputSanitizer.cs b/SafeVault.App/Security/InputSanitizer.cs
new file mode 100644
index 0000000..c1e1244
--- /dev/null
+++ b/SafeVault.App/Security/InputSanitizer.cs
@@ -0,0 +1,108 @@
+using System.Text.RegularExpressions;
+
+namespace SafeVault.App.Security;
+
+///
+/// Provides input sanitization to prevent XSS and SQL injection attacks
+///
+public class InputSanitizer
+{
+ ///
+ /// Sanitizes input to prevent XSS attacks by encoding HTML special characters
+ ///
+ public static string SanitizeForXss(string input)
+ {
+ if (string.IsNullOrEmpty(input))
+ return input;
+
+ return input
+ .Replace("&", "&")
+ .Replace("<", "<")
+ .Replace(">", ">")
+ .Replace("\"", """)
+ .Replace("'", "'")
+ .Replace("/", "/");
+ }
+
+ ///
+ /// Validates input for SQL injection patterns
+ /// Returns true if input contains suspicious SQL patterns
+ ///
+ public static bool ContainsSqlInjectionPattern(string input)
+ {
+ if (string.IsNullOrEmpty(input))
+ return false;
+
+ // Common SQL injection patterns
+ string[] sqlPatterns = new[]
+ {
+ @"(\b(SELECT|INSERT|UPDATE|DELETE|DROP|CREATE|ALTER|EXEC|EXECUTE|UNION|DECLARE)\b)",
+ @"(--|\#|\/\*|\*\/)",
+ @"('|(;|=))",
+ @"(\bOR\b\s+\d+\s*=\s*\d+)",
+ @"(\bAND\b\s+\d+\s*=\s*\d+)",
+ @"(xp_|sp_)"
+ };
+
+ foreach (var pattern in sqlPatterns)
+ {
+ if (Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ ///
+ /// Validates email format
+ ///
+ public static bool IsValidEmail(string email)
+ {
+ if (string.IsNullOrWhiteSpace(email))
+ return false;
+
+ try
+ {
+ var emailPattern = @"^[^@\s]+@[^@\s]+\.[^@\s]+$";
+ return Regex.IsMatch(email, emailPattern, RegexOptions.IgnoreCase);
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Validates username format (alphanumeric and underscore only)
+ ///
+ public static bool IsValidUsername(string username)
+ {
+ if (string.IsNullOrWhiteSpace(username))
+ return false;
+
+ var usernamePattern = @"^[a-zA-Z0-9_]{3,20}$";
+ return Regex.IsMatch(username, usernamePattern);
+ }
+
+ ///
+ /// Sanitizes input for safe usage in SQL context
+ /// Note: This should be used in conjunction with parameterized queries
+ ///
+ public static string SanitizeForSql(string input)
+ {
+ if (string.IsNullOrEmpty(input))
+ return input;
+
+ // Remove or escape dangerous characters
+ return input
+ .Replace("'", "''")
+ .Replace(";", "")
+ .Replace("--", "")
+ .Replace("/*", "")
+ .Replace("*/", "")
+ .Replace("xp_", "")
+ .Replace("sp_", "");
+ }
+}
diff --git a/SafeVault.App/Security/RoleAuthorization.cs b/SafeVault.App/Security/RoleAuthorization.cs
new file mode 100644
index 0000000..e024ec4
--- /dev/null
+++ b/SafeVault.App/Security/RoleAuthorization.cs
@@ -0,0 +1,77 @@
+using SafeVault.App.Models;
+
+namespace SafeVault.App.Security;
+
+///
+/// Provides role-based authorization checks
+///
+public class RoleAuthorization
+{
+ public const string AdminRole = "admin";
+ public const string UserRole = "user";
+
+ ///
+ /// Checks if a user has the specified role
+ ///
+ public static bool HasRole(User user, string role)
+ {
+ if (user == null || string.IsNullOrEmpty(role))
+ return false;
+
+ return user.Role.Equals(role, StringComparison.OrdinalIgnoreCase);
+ }
+
+ ///
+ /// Checks if a user is an administrator
+ ///
+ public static bool IsAdmin(User user)
+ {
+ return HasRole(user, AdminRole);
+ }
+
+ ///
+ /// Checks if a user is a regular user
+ ///
+ public static bool IsUser(User user)
+ {
+ return HasRole(user, UserRole);
+ }
+
+ ///
+ /// Authorizes access based on required role
+ /// Throws UnauthorizedAccessException if user doesn't have the required role
+ ///
+ public static void RequireRole(User user, string requiredRole)
+ {
+ if (!HasRole(user, requiredRole))
+ {
+ throw new UnauthorizedAccessException($"User does not have the required role: {requiredRole}");
+ }
+ }
+
+ ///
+ /// Authorizes admin access
+ /// Throws UnauthorizedAccessException if user is not an admin
+ ///
+ public static void RequireAdmin(User user)
+ {
+ RequireRole(user, AdminRole);
+ }
+
+ ///
+ /// Checks if user can access a resource
+ /// Admins can access everything, users can only access their own resources
+ ///
+ public static bool CanAccessResource(User user, int resourceOwnerId)
+ {
+ if (user == null)
+ return false;
+
+ // Admins can access everything
+ if (IsAdmin(user))
+ return true;
+
+ // Users can only access their own resources
+ return user.Id == resourceOwnerId;
+ }
+}
diff --git a/SafeVault.slnx b/SafeVault.slnx
new file mode 100644
index 0000000..7ae1ed5
--- /dev/null
+++ b/SafeVault.slnx
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/Tests/TestAuthentication.cs b/Tests/TestAuthentication.cs
new file mode 100644
index 0000000..74bf8b6
--- /dev/null
+++ b/Tests/TestAuthentication.cs
@@ -0,0 +1,248 @@
+using NUnit.Framework;
+using SafeVault.App.Models;
+using SafeVault.App.Security;
+
+namespace Tests;
+
+[TestFixture]
+public class TestAuthentication
+{
+ [Test]
+ public void Test_HashPassword_GeneratesUniqueHashes()
+ {
+ // Arrange
+ string password = "TestPassword123!";
+
+ // Act
+ string hash1 = AuthService.HashPassword(password);
+ string hash2 = AuthService.HashPassword(password);
+
+ // Assert
+ Assert.That(hash1, Is.Not.Null);
+ Assert.That(hash2, Is.Not.Null);
+ Assert.That(hash1, Is.Not.EqualTo(hash2)); // BCrypt uses random salt
+ Assert.That(hash1, Does.StartWith("$2")); // BCrypt format
+ }
+
+ [Test]
+ public void Test_HashPassword_ThrowsOnNullOrEmpty()
+ {
+ // Act & Assert
+ Assert.Throws(() => AuthService.HashPassword(null!));
+ Assert.Throws(() => AuthService.HashPassword(""));
+ }
+
+ [Test]
+ public void Test_VerifyPassword_ValidPassword()
+ {
+ // Arrange
+ string password = "TestPassword123!";
+ string hash = AuthService.HashPassword(password);
+
+ // Act
+ bool isValid = AuthService.VerifyPassword(password, hash);
+
+ // Assert
+ Assert.That(isValid, Is.True);
+ }
+
+ [Test]
+ public void Test_VerifyPassword_InvalidPassword()
+ {
+ // Arrange
+ string password = "TestPassword123!";
+ string wrongPassword = "WrongPassword123!";
+ string hash = AuthService.HashPassword(password);
+
+ // Act
+ bool isValid = AuthService.VerifyPassword(wrongPassword, hash);
+
+ // Assert
+ Assert.That(isValid, Is.False);
+ }
+
+ [Test]
+ public void Test_VerifyPassword_HandlesNullAndEmpty()
+ {
+ // Arrange
+ string hash = AuthService.HashPassword("TestPassword123!");
+
+ // Act & Assert
+ Assert.That(AuthService.VerifyPassword(null!, hash), Is.False);
+ Assert.That(AuthService.VerifyPassword("", hash), Is.False);
+ Assert.That(AuthService.VerifyPassword("password", null!), Is.False);
+ Assert.That(AuthService.VerifyPassword("password", ""), Is.False);
+ }
+
+ [Test]
+ public void Test_Login_ValidCredentials()
+ {
+ // Arrange
+ var users = new List
+ {
+ new User
+ {
+ Id = 1,
+ Username = "testuser",
+ Email = "test@example.com",
+ PasswordHash = AuthService.HashPassword("TestPass123!"),
+ Role = "user"
+ }
+ };
+
+ // Act
+ var result = AuthService.Login("testuser", "TestPass123!", users);
+
+ // Assert
+ Assert.That(result, Is.Not.Null);
+ Assert.That(result!.Username, Is.EqualTo("testuser"));
+ }
+
+ [Test]
+ public void Test_Login_InvalidPassword()
+ {
+ // Arrange
+ var users = new List
+ {
+ new User
+ {
+ Id = 1,
+ Username = "testuser",
+ Email = "test@example.com",
+ PasswordHash = AuthService.HashPassword("TestPass123!"),
+ Role = "user"
+ }
+ };
+
+ // Act
+ var result = AuthService.Login("testuser", "WrongPassword", users);
+
+ // Assert
+ Assert.That(result, Is.Null);
+ }
+
+ [Test]
+ public void Test_Login_InvalidUsername()
+ {
+ // Arrange
+ var users = new List
+ {
+ new User
+ {
+ Id = 1,
+ Username = "testuser",
+ Email = "test@example.com",
+ PasswordHash = AuthService.HashPassword("TestPass123!"),
+ Role = "user"
+ }
+ };
+
+ // Act
+ var result = AuthService.Login("wronguser", "TestPass123!", users);
+
+ // Assert
+ Assert.That(result, Is.Null);
+ }
+
+ [Test]
+ public void Test_Login_NullOrEmptyCredentials()
+ {
+ // Arrange
+ var users = new List();
+
+ // Act & Assert
+ Assert.That(AuthService.Login(null!, "password", users), Is.Null);
+ Assert.That(AuthService.Login("", "password", users), Is.Null);
+ Assert.That(AuthService.Login("username", null!, users), Is.Null);
+ Assert.That(AuthService.Login("username", "", users), Is.Null);
+ }
+
+ [Test]
+ public void Test_Login_CaseInsensitiveUsername()
+ {
+ // Arrange
+ var users = new List
+ {
+ new User
+ {
+ Id = 1,
+ Username = "TestUser",
+ Email = "test@example.com",
+ PasswordHash = AuthService.HashPassword("TestPass123!"),
+ Role = "user"
+ }
+ };
+
+ // Act
+ var result1 = AuthService.Login("testuser", "TestPass123!", users);
+ var result2 = AuthService.Login("TESTUSER", "TestPass123!", users);
+
+ // Assert
+ Assert.That(result1, Is.Not.Null);
+ Assert.That(result2, Is.Not.Null);
+ }
+
+ [Test]
+ public void Test_IsStrongPassword_ValidPasswords()
+ {
+ // Arrange & Act & Assert
+ Assert.That(AuthService.IsStrongPassword("StrongPass123!"), Is.True);
+ Assert.That(AuthService.IsStrongPassword("Test@123Pass"), Is.True);
+ Assert.That(AuthService.IsStrongPassword("Abcd1234!@#$"), Is.True);
+ }
+
+ [Test]
+ public void Test_IsStrongPassword_WeakPasswords()
+ {
+ // Arrange & Act & Assert
+ Assert.That(AuthService.IsStrongPassword("weak"), Is.False); // Too short
+ Assert.That(AuthService.IsStrongPassword("password"), Is.False); // No uppercase, digit, special
+ Assert.That(AuthService.IsStrongPassword("PASSWORD123!"), Is.False); // No lowercase
+ Assert.That(AuthService.IsStrongPassword("Password!"), Is.False); // No digit
+ Assert.That(AuthService.IsStrongPassword("Password123"), Is.False); // No special char
+ Assert.That(AuthService.IsStrongPassword(""), Is.False);
+ Assert.That(AuthService.IsStrongPassword(null!), Is.False);
+ }
+
+ [Test]
+ public void Test_PasswordHashing_ResistsBruteForce()
+ {
+ // Arrange
+ string password = "TestPassword123!";
+
+ // Act - Measure time for hashing (BCrypt should be slow by design)
+ var startTime = DateTime.Now;
+ string hash = AuthService.HashPassword(password);
+ var endTime = DateTime.Now;
+ var duration = endTime - startTime;
+
+ // Assert
+ Assert.That(hash, Is.Not.Null);
+ Assert.That(duration.TotalMilliseconds, Is.GreaterThan(10)); // BCrypt should take some time
+ }
+
+ [Test]
+ public void Test_Authentication_PreventsTimingAttacks()
+ {
+ // Arrange
+ var users = new List
+ {
+ new User
+ {
+ Id = 1,
+ Username = "testuser",
+ Email = "test@example.com",
+ PasswordHash = AuthService.HashPassword("TestPass123!"),
+ Role = "user"
+ }
+ };
+
+ // Act - Both should return null (fail) but timing should be similar
+ var result1 = AuthService.Login("wronguser", "TestPass123!", users);
+ var result2 = AuthService.Login("testuser", "WrongPassword", users);
+
+ // Assert
+ Assert.That(result1, Is.Null);
+ Assert.That(result2, Is.Null);
+ }
+}
diff --git a/Tests/TestAuthorization.cs b/Tests/TestAuthorization.cs
new file mode 100644
index 0000000..466eff2
--- /dev/null
+++ b/Tests/TestAuthorization.cs
@@ -0,0 +1,223 @@
+using NUnit.Framework;
+using SafeVault.App.Models;
+using SafeVault.App.Security;
+
+namespace Tests;
+
+[TestFixture]
+public class TestAuthorization
+{
+ private User _adminUser = null!;
+ private User _regularUser = null!;
+
+ [SetUp]
+ public void Setup()
+ {
+ _adminUser = new User
+ {
+ Id = 1,
+ Username = "admin",
+ Email = "admin@safevault.com",
+ PasswordHash = AuthService.HashPassword("AdminPass123!"),
+ Role = "admin"
+ };
+
+ _regularUser = new User
+ {
+ Id = 2,
+ Username = "john_doe",
+ Email = "john@example.com",
+ PasswordHash = AuthService.HashPassword("UserPass123!"),
+ Role = "user"
+ };
+ }
+
+ [Test]
+ public void Test_HasRole_AdminUser()
+ {
+ // Act & Assert
+ Assert.That(RoleAuthorization.HasRole(_adminUser, "admin"), Is.True);
+ Assert.That(RoleAuthorization.HasRole(_adminUser, "user"), Is.False);
+ }
+
+ [Test]
+ public void Test_HasRole_RegularUser()
+ {
+ // Act & Assert
+ Assert.That(RoleAuthorization.HasRole(_regularUser, "user"), Is.True);
+ Assert.That(RoleAuthorization.HasRole(_regularUser, "admin"), Is.False);
+ }
+
+ [Test]
+ public void Test_HasRole_CaseInsensitive()
+ {
+ // Act & Assert
+ Assert.That(RoleAuthorization.HasRole(_adminUser, "ADMIN"), Is.True);
+ Assert.That(RoleAuthorization.HasRole(_adminUser, "Admin"), Is.True);
+ Assert.That(RoleAuthorization.HasRole(_regularUser, "USER"), Is.True);
+ }
+
+ [Test]
+ public void Test_HasRole_NullUser()
+ {
+ // Act & Assert
+ Assert.That(RoleAuthorization.HasRole(null!, "admin"), Is.False);
+ }
+
+ [Test]
+ public void Test_IsAdmin_AdminUser()
+ {
+ // Act & Assert
+ Assert.That(RoleAuthorization.IsAdmin(_adminUser), Is.True);
+ }
+
+ [Test]
+ public void Test_IsAdmin_RegularUser()
+ {
+ // Act & Assert
+ Assert.That(RoleAuthorization.IsAdmin(_regularUser), Is.False);
+ }
+
+ [Test]
+ public void Test_IsUser_RegularUser()
+ {
+ // Act & Assert
+ Assert.That(RoleAuthorization.IsUser(_regularUser), Is.True);
+ }
+
+ [Test]
+ public void Test_IsUser_AdminUser()
+ {
+ // Act & Assert
+ Assert.That(RoleAuthorization.IsUser(_adminUser), Is.False);
+ }
+
+ [Test]
+ public void Test_RequireRole_Success()
+ {
+ // Act & Assert - Should not throw
+ Assert.DoesNotThrow(() => RoleAuthorization.RequireRole(_adminUser, "admin"));
+ Assert.DoesNotThrow(() => RoleAuthorization.RequireRole(_regularUser, "user"));
+ }
+
+ [Test]
+ public void Test_RequireRole_Failure()
+ {
+ // Act & Assert
+ var ex1 = Assert.Throws(() =>
+ RoleAuthorization.RequireRole(_regularUser, "admin"));
+ Assert.That(ex1!.Message, Does.Contain("admin"));
+
+ var ex2 = Assert.Throws(() =>
+ RoleAuthorization.RequireRole(_adminUser, "user"));
+ Assert.That(ex2!.Message, Does.Contain("user"));
+ }
+
+ [Test]
+ public void Test_RequireAdmin_AdminUser()
+ {
+ // Act & Assert - Should not throw
+ Assert.DoesNotThrow(() => RoleAuthorization.RequireAdmin(_adminUser));
+ }
+
+ [Test]
+ public void Test_RequireAdmin_RegularUser()
+ {
+ // Act & Assert
+ var ex = Assert.Throws(() =>
+ RoleAuthorization.RequireAdmin(_regularUser));
+ Assert.That(ex!.Message, Does.Contain("admin"));
+ }
+
+ [Test]
+ public void Test_CanAccessResource_AdminCanAccessAll()
+ {
+ // Act & Assert
+ Assert.That(RoleAuthorization.CanAccessResource(_adminUser, 1), Is.True);
+ Assert.That(RoleAuthorization.CanAccessResource(_adminUser, 2), Is.True);
+ Assert.That(RoleAuthorization.CanAccessResource(_adminUser, 999), Is.True);
+ }
+
+ [Test]
+ public void Test_CanAccessResource_UserCanAccessOwn()
+ {
+ // Act & Assert
+ Assert.That(RoleAuthorization.CanAccessResource(_regularUser, 2), Is.True); // Own resource
+ Assert.That(RoleAuthorization.CanAccessResource(_regularUser, 1), Is.False); // Other's resource
+ Assert.That(RoleAuthorization.CanAccessResource(_regularUser, 999), Is.False); // Other's resource
+ }
+
+ [Test]
+ public void Test_CanAccessResource_NullUser()
+ {
+ // Act & Assert
+ Assert.That(RoleAuthorization.CanAccessResource(null!, 1), Is.False);
+ }
+
+ [Test]
+ public void Test_PrivilegeEscalation_Prevention()
+ {
+ // Arrange
+ var maliciousUser = new User
+ {
+ Id = 3,
+ Username = "hacker",
+ Email = "hacker@example.com",
+ PasswordHash = AuthService.HashPassword("HackerPass123!"),
+ Role = "user" // Try to escalate to admin
+ };
+
+ // Act - Try to access admin resources
+ bool canAccessAdminResource = RoleAuthorization.CanAccessResource(maliciousUser, 1);
+ bool isAdmin = RoleAuthorization.IsAdmin(maliciousUser);
+
+ // Assert
+ Assert.That(canAccessAdminResource, Is.False);
+ Assert.That(isAdmin, Is.False);
+ Assert.Throws(() =>
+ RoleAuthorization.RequireAdmin(maliciousUser));
+ }
+
+ [Test]
+ public void Test_Authorization_ConsistentBehavior()
+ {
+ // Verify that multiple checks return consistent results
+ for (int i = 0; i < 5; i++)
+ {
+ Assert.That(RoleAuthorization.IsAdmin(_adminUser), Is.True);
+ Assert.That(RoleAuthorization.IsAdmin(_regularUser), Is.False);
+ Assert.That(RoleAuthorization.CanAccessResource(_adminUser, 999), Is.True);
+ Assert.That(RoleAuthorization.CanAccessResource(_regularUser, 999), Is.False);
+ }
+ }
+
+ [Test]
+ public void Test_RoleConstants()
+ {
+ // Verify role constants are correct
+ Assert.That(RoleAuthorization.AdminRole, Is.EqualTo("admin"));
+ Assert.That(RoleAuthorization.UserRole, Is.EqualTo("user"));
+ }
+
+ [Test]
+ public void Test_MultipleUsers_IndependentAuthorization()
+ {
+ // Arrange
+ var user1 = new User { Id = 10, Username = "user1", Role = "user" };
+ var user2 = new User { Id = 20, Username = "user2", Role = "user" };
+ var user3 = new User { Id = 30, Username = "user3", Role = "user" };
+
+ // Act & Assert - Each user can only access their own resources
+ Assert.That(RoleAuthorization.CanAccessResource(user1, 10), Is.True);
+ Assert.That(RoleAuthorization.CanAccessResource(user1, 20), Is.False);
+ Assert.That(RoleAuthorization.CanAccessResource(user1, 30), Is.False);
+
+ Assert.That(RoleAuthorization.CanAccessResource(user2, 10), Is.False);
+ Assert.That(RoleAuthorization.CanAccessResource(user2, 20), Is.True);
+ Assert.That(RoleAuthorization.CanAccessResource(user2, 30), Is.False);
+
+ Assert.That(RoleAuthorization.CanAccessResource(user3, 10), Is.False);
+ Assert.That(RoleAuthorization.CanAccessResource(user3, 20), Is.False);
+ Assert.That(RoleAuthorization.CanAccessResource(user3, 30), Is.True);
+ }
+}
diff --git a/Tests/TestInputValidation.cs b/Tests/TestInputValidation.cs
new file mode 100644
index 0000000..a4ba68e
--- /dev/null
+++ b/Tests/TestInputValidation.cs
@@ -0,0 +1,151 @@
+using NUnit.Framework;
+using SafeVault.App.Security;
+
+namespace Tests;
+
+[TestFixture]
+public class TestInputValidation
+{
+ [Test]
+ public void Test_SanitizeForXss_RemovesScriptTags()
+ {
+ // Arrange
+ string maliciousInput = "";
+
+ // Act
+ string sanitized = InputSanitizer.SanitizeForXss(maliciousInput);
+
+ // Assert
+ Assert.That(sanitized, Does.Not.Contain(""));
+ Assert.That(sanitized, Does.Contain("<script>"));
+ }
+
+ [Test]
+ public void Test_SanitizeForXss_EncodesSpecialCharacters()
+ {
+ // Arrange
+ string input = "<>&\"'/";
+
+ // Act
+ string sanitized = InputSanitizer.SanitizeForXss(input);
+
+ // Assert
+ Assert.That(sanitized, Is.EqualTo("<>&"'/"));
+ }
+
+ [Test]
+ public void Test_SanitizeForXss_HandlesNullAndEmpty()
+ {
+ // Act & Assert
+ Assert.That(InputSanitizer.SanitizeForXss(null), Is.Null);
+ Assert.That(InputSanitizer.SanitizeForXss(""), Is.EqualTo(""));
+ }
+
+ [Test]
+ public void Test_ContainsSqlInjectionPattern_DetectsSqlKeywords()
+ {
+ // Arrange & Act & Assert
+ Assert.That(InputSanitizer.ContainsSqlInjectionPattern("admin' OR '1'='1"), Is.True);
+ Assert.That(InputSanitizer.ContainsSqlInjectionPattern("SELECT * FROM Users"), Is.True);
+ Assert.That(InputSanitizer.ContainsSqlInjectionPattern("'; DROP TABLE Users; --"), Is.True);
+ Assert.That(InputSanitizer.ContainsSqlInjectionPattern("admin'--"), Is.True);
+ Assert.That(InputSanitizer.ContainsSqlInjectionPattern("1' UNION SELECT"), Is.True);
+ }
+
+ [Test]
+ public void Test_ContainsSqlInjectionPattern_AllowsNormalInput()
+ {
+ // Arrange & Act & Assert
+ Assert.That(InputSanitizer.ContainsSqlInjectionPattern("john_doe"), Is.False);
+ Assert.That(InputSanitizer.ContainsSqlInjectionPattern("user@example.com"), Is.False);
+ Assert.That(InputSanitizer.ContainsSqlInjectionPattern("normaltext123"), Is.False);
+ }
+
+ [Test]
+ public void Test_IsValidEmail_AcceptsValidEmails()
+ {
+ // Arrange & Act & Assert
+ Assert.That(InputSanitizer.IsValidEmail("user@example.com"), Is.True);
+ Assert.That(InputSanitizer.IsValidEmail("test.user@domain.co.uk"), Is.True);
+ Assert.That(InputSanitizer.IsValidEmail("name+tag@example.com"), Is.True);
+ }
+
+ [Test]
+ public void Test_IsValidEmail_RejectsInvalidEmails()
+ {
+ // Arrange & Act & Assert
+ Assert.That(InputSanitizer.IsValidEmail("notanemail"), Is.False);
+ Assert.That(InputSanitizer.IsValidEmail("@example.com"), Is.False);
+ Assert.That(InputSanitizer.IsValidEmail("user@"), Is.False);
+ Assert.That(InputSanitizer.IsValidEmail(""), Is.False);
+ Assert.That(InputSanitizer.IsValidEmail(null), Is.False);
+ }
+
+ [Test]
+ public void Test_IsValidUsername_AcceptsValidUsernames()
+ {
+ // Arrange & Act & Assert
+ Assert.That(InputSanitizer.IsValidUsername("john_doe"), Is.True);
+ Assert.That(InputSanitizer.IsValidUsername("user123"), Is.True);
+ Assert.That(InputSanitizer.IsValidUsername("admin"), Is.True);
+ Assert.That(InputSanitizer.IsValidUsername("test_user_123"), Is.True);
+ }
+
+ [Test]
+ public void Test_IsValidUsername_RejectsInvalidUsernames()
+ {
+ // Arrange & Act & Assert
+ Assert.That(InputSanitizer.IsValidUsername("ab"), Is.False); // Too short
+ Assert.That(InputSanitizer.IsValidUsername("a".PadRight(21, 'a')), Is.False); // Too long
+ Assert.That(InputSanitizer.IsValidUsername("user@name"), Is.False); // Invalid char
+ Assert.That(InputSanitizer.IsValidUsername("user name"), Is.False); // Space
+ Assert.That(InputSanitizer.IsValidUsername("user-name"), Is.False); // Hyphen
+ Assert.That(InputSanitizer.IsValidUsername(""), Is.False);
+ Assert.That(InputSanitizer.IsValidUsername(null), Is.False);
+ }
+
+ [Test]
+ public void Test_SanitizeForSql_RemovesDangerousCharacters()
+ {
+ // Arrange
+ string input = "test'; DROP TABLE--";
+
+ // Act
+ string sanitized = InputSanitizer.SanitizeForSql(input);
+
+ // Assert
+ Assert.That(sanitized, Does.Not.Contain(";"));
+ Assert.That(sanitized, Does.Not.Contain("--"));
+ }
+
+ [Test]
+ public void Test_XssAttackVectors_AreBlocked()
+ {
+ // Test various XSS attack vectors with HTML tags
+ string[] xssVectors = new[]
+ {
+ "
",
+ "