test(security): lock tenant isolation on match-score and status-suggestion
Cross-user access to the new endpoints returns NotFound (carried by the JobTrackerContext global query filters). Regression guard for the class of tenant-leak bugs found in the M013-M015 assessments. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -38,6 +38,42 @@ public sealed class JobApplicationsAuthorizationTests
|
|||||||
Assert.IsType<NotFoundResult>(result.Result);
|
Assert.IsType<NotFoundResult>(result.Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetMatchScore_returns_not_found_for_other_users_job()
|
||||||
|
{
|
||||||
|
var dbName = Guid.NewGuid().ToString();
|
||||||
|
await using var ownerDb = CreateDb(dbName, "owner-1");
|
||||||
|
var company = new Company { Name = "Acme", OwnerUserId = "owner-1" };
|
||||||
|
ownerDb.Companies.Add(company);
|
||||||
|
await ownerDb.SaveChangesAsync();
|
||||||
|
ownerDb.JobApplications.Add(new JobApplication { JobTitle = "Secret", CompanyId = company.Id, OwnerUserId = "owner-1", Description = "C# .NET" });
|
||||||
|
await ownerDb.SaveChangesAsync();
|
||||||
|
var jobId = await ownerDb.JobApplications.Select(j => j.Id).FirstAsync();
|
||||||
|
|
||||||
|
await using var attackerDb = CreateDb(dbName, "other-user");
|
||||||
|
var result = await CreateController(attackerDb).GetMatchScore(jobId, CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.IsType<NotFoundResult>(result.Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetStatusSuggestion_returns_not_found_for_other_users_job()
|
||||||
|
{
|
||||||
|
var dbName = Guid.NewGuid().ToString();
|
||||||
|
await using var ownerDb = CreateDb(dbName, "owner-1");
|
||||||
|
var company = new Company { Name = "Acme", OwnerUserId = "owner-1" };
|
||||||
|
ownerDb.Companies.Add(company);
|
||||||
|
await ownerDb.SaveChangesAsync();
|
||||||
|
ownerDb.JobApplications.Add(new JobApplication { JobTitle = "Secret", CompanyId = company.Id, OwnerUserId = "owner-1" });
|
||||||
|
await ownerDb.SaveChangesAsync();
|
||||||
|
var jobId = await ownerDb.JobApplications.Select(j => j.Id).FirstAsync();
|
||||||
|
|
||||||
|
await using var attackerDb = CreateDb(dbName, "other-user");
|
||||||
|
var result = await CreateController(attackerDb).GetStatusSuggestion(jobId, CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.IsType<NotFoundResult>(result.Result);
|
||||||
|
}
|
||||||
|
|
||||||
private static JobTrackerContext CreateDb(string dbName, string? userId)
|
private static JobTrackerContext CreateDb(string dbName, string? userId)
|
||||||
{
|
{
|
||||||
var options = new DbContextOptionsBuilder<JobTrackerContext>()
|
var options = new DbContextOptionsBuilder<JobTrackerContext>()
|
||||||
|
|||||||
Reference in New Issue
Block a user