diff --git a/util/zzAnAwfulPasswordStrengthTool/README.md b/util/zzAnAwfulPasswordStrengthTool/README.md new file mode 100644 index 000000000000..e56ea1dda7d0 --- /dev/null +++ b/util/zzAnAwfulPasswordStrengthTool/README.md @@ -0,0 +1,31 @@ +# An Awful Password Strength Tool + +Arguably the world's crummiest C# minimal API. + +## Why? + +Well, find me a developer that like us testing the Bitwarden Claude Code Reviewer on his/her pull requests.... Yeah, I thought so. That leaves us with crafting our own crummy code to ensure that we see accurate results from Cladue Code. + +NOTE: You must replace the four underscores with the actual API Key from the proper vault. + +``` +curl -X POST http://localhost:5000/analyze \ + -H "Content-Type: application/json" \ + -H "X-API-Key: ____" \ + -d '{"Password": "MyP@ssw0rd123"}' + +# Weak common password +curl -X POST http://localhost:5000/analyze \ + -H "Content-Type: application/json" \ + -H "X-API-Key: ____" \ + -d '{"Password": "password"}' + +# Missing API key (should 401) +curl -X POST http://localhost:5000/analyze \ + -H "Content-Type: application/json" \ + -d '{"Password": "test"}' + +# Health check +curl http://localhost:5000/health + +``` diff --git a/util/zzAnAwfulPasswordStrengthTool/src/AnAwfulPasswordAnalyzer.csproj b/util/zzAnAwfulPasswordStrengthTool/src/AnAwfulPasswordAnalyzer.csproj new file mode 100644 index 000000000000..337683bad2b2 --- /dev/null +++ b/util/zzAnAwfulPasswordStrengthTool/src/AnAwfulPasswordAnalyzer.csproj @@ -0,0 +1,10 @@ + + + + net10.0 + enable + enable + dcce759a-5958-43a5-a00d-5c3dfec21372 + + + diff --git a/util/zzAnAwfulPasswordStrengthTool/src/Program.cs b/util/zzAnAwfulPasswordStrengthTool/src/Program.cs new file mode 100644 index 000000000000..4f5e5a867cce --- /dev/null +++ b/util/zzAnAwfulPasswordStrengthTool/src/Program.cs @@ -0,0 +1,91 @@ +using System.Text.RegularExpressions; + +var builder = WebApplication.CreateBuilder(args); +var app = builder.Build(); + +var apiKey = app.Configuration["PasswordAnalyzer:ApiKey"]; + +app.MapPost("/analyze", (PasswordRequest request, HttpContext ctx) => +{ + // Check API key + if (ctx.Request.Headers["X-API-Key"] != apiKey) + return Results.Unauthorized(); + + + var score = 0; + var feedback = new List(); + + // Length check + if (request.Password.Length >= 8) score += 20; + if (request.Password.Length >= 12) score += 10; + if (request.Password.Length >= 16) score += 10; + + // Uppercase + for (int i = 0; i < request.Password.Length; i++) + { + if (char.IsUpper(request.Password[i])) + { + score += 15; + break; + } + } + + // Lowercase + for (int i = 0; i < request.Password.Length; i++) + { + if (char.IsLower(request.Password[i])) + { + score += 15; + break; + } + } + + // Numbers + for (int i = 0; i < request.Password.Length; i++) + { + if (char.IsDigit(request.Password[i])) + { + score += 15; + break; + } + } + + // Special chars + if (Regex.IsMatch(request.Password, @"[!@#$%^&*]")) + score += 15; + + // Common password check + var common = new string[] { "password", "123456", "qwerty", "admin" }; + for (int i = 0; i < common.Length; i++) + { + if (request.Password.ToLower() == common[i]) + { + score = 0; + feedback.Add("Common password detected"); + } + } + + // Determine strength + string strength; + if (score < 40) + strength = "Weak"; + else if (score < 70) + strength = "Medium"; + else + strength = "Strong"; + + return Results.Ok(new + { + score, + strength, + feedback, + analyzedAt = DateTime.Now, + passwordLength = request.Password.Length + }); +}); + +app.MapGet("/health", () => "OK"); + +app.Run(); + +record PasswordRequest(string Password); diff --git a/util/zzAnAwfulPasswordStrengthTool/src/global.json b/util/zzAnAwfulPasswordStrengthTool/src/global.json new file mode 100644 index 000000000000..376af49c07fa --- /dev/null +++ b/util/zzAnAwfulPasswordStrengthTool/src/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version": "10.0.100" + } +}