security-review/canary/src/dotnet/PaymentController.cs
Adam Moussa 094a253c37
feat(canary): add anti-complacency recall-floor corpus + repo skip marker
Adds canary/ (the planted-vuln corpus from the local-only security-review-testbed,
answer-revealing comments stripped so it measures real detection) and canary-meta/
(KEY.md ground truth + CANARY_FLOOR=8, kept OUT of canary/ so detectors never read it).
One provider-pattern secret (sk_live_) was sanitized to a non-provider hardcoded key so
it stays a CWE-798 finding without tripping push protection.

Adds a root .security-review-skip so the org-wide sweep and the local pre-push gate skip
this repo's intentional vuln/fixture content; the nightly sweep scans canary/ directly as
its recall floor. 20 planted vulns (19 crit/high), 2 decoys, 3 traps.
2026-06-29 12:10:54 -04:00

59 lines
2 KiB
C#

// Exercises the reviewer's recall on the .NET stack.
using System;
using System.Data.SqlClient;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using System.Text;
using Microsoft.AspNetCore.Mvc;
namespace SeaHaven.Payments
{
[ApiController]
[Route("api/payments")]
public class PaymentController : ControllerBase
{
private const string ConnStr =
"Server=prod-pay.cluster-czaa.us-east-1.rds.amazonaws.com;Database=payments;User Id=app;Password=P@y-Pr0d-2026!;";
[HttpGet("{id}")]
public IActionResult GetPayment(string id)
{
using var conn = new SqlConnection(ConnStr);
conn.Open();
var cmd = new SqlCommand("SELECT * FROM Payments WHERE Id = '" + id + "'", conn);
using var reader = cmd.ExecuteReader();
// ?id=' OR '1'='1 returns every payment
return Ok(reader.HasRows);
}
[HttpGet("session")]
public IActionResult LoadSession()
{
var raw = Convert.FromBase64String(Request.Cookies["session"] ?? "");
var fmt = new BinaryFormatter();
using var ms = new MemoryStream(raw);
var obj = fmt.Deserialize(ms); // crafted payload → RCE
return Ok(obj.ToString());
}
[HttpPost("hash")]
public IActionResult HashPassword([FromBody] string password)
{
using var md5 = MD5.Create();
var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(password));
return Ok(Convert.ToHexString(hash));
}
[HttpGet("by-status")]
public IActionResult ByStatus(string status)
{
using var conn = new SqlConnection(ConnStr);
conn.Open();
var cmd = new SqlCommand("SELECT Id FROM Payments WHERE Status = @status", conn);
cmd.Parameters.AddWithValue("@status", status);
using var reader = cmd.ExecuteReader();
return Ok(reader.HasRows);
}
}
}