Files
jobtrackingapp/docs/security-assessments/M015-authorization-replay-report.md

131 lines
4.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# M015 Cross-User Authorization Replay Report
This report covers the follow-up tenant-boundary work after `M013` and `M014`.
Related artifacts:
- `docs/security-assessments/M013-adversarial-security-assessment.md`
- `docs/security-assessments/M014-security-remediation-verification.md`
- `docs/security-assessments/M015-hostile-fixture-setup.md`
- `docs/security-assessments/M015-hostile-fixture-setup.json`
- `docs/security-assessments/M015-s02-probe-results.json`
## Test Setup
A dedicated hostile-test SQLite database was created from the current EF model because the default development DB was missing core domain tables needed for real authorization probes.
Fixture runtime:
- clean SQLite DB under `.tmp/m015-fixture`
- API started with `Data__Root=/home/pi/development/JobTracker/.tmp/m015-fixture`
- registration temporarily enabled for the fixture runtime
- two real local users created through the API:
- `alice.m015@example.com`
- `bob.m015@example.com`
Alice-owned fixture resources created through the real API:
- `company_id = 1`
- `job_id = 1`
- `correspondence_id = 1`
- `attachment_id = 1`
All mutating requests used the real cookie + CSRF contract.
## Cross-User Probe Summary
Bob targeted Alices fixture ids with a real authenticated session.
### Defended in this pass
The following probes failed closed with `404` when Bob targeted Alices resources:
- `GET /api/attachments/1`
- `GET /api/attachments/download/1`
- `PATCH /api/attachments/1`
- `DELETE /api/attachments/1`
- `GET /api/correspondence/1`
- `DELETE /api/correspondence/1`
- `GET /api/jobapplications/1`
- `PUT /api/jobapplications/1`
- `PATCH /api/jobapplications/1/followup`
- `GET /api/jobapplications/1/timeline`
- `GET /api/jobapplications/1/tailored-cv-draft`
- `GET /api/jobapplications/1/followup-draft`
These routes did not expose or mutate Alice-owned data in this hostile fixture pass.
## Confirmed Finding
### Cross-user read leak on job history
- **Category:** Authorization / data exposure
- **Endpoint:** `GET /api/jobapplications/{id}/history`
- **Risk:** **Medium**
#### Vulnerability
Before the fix, Bob could request Alices job history by raw job id and receive Alices `JobEvent` rows.
Observed pre-fix response:
- `GET /api/jobapplications/1/history` as Bob
- `200 OK`
- payload included Alice-owned event data, including the `Created` event for Alices job
#### Example exploit input
```http
GET /api/jobapplications/1/history
Cookie: jobtracker_auth=<bob session cookie>
```
#### Root cause
Two issues combined:
1. `GetHistory(...)` queried `JobEvents` directly by `JobApplicationId` without verifying that the parent job belonged to the current user.
2. `JobEvent` had no owner-scoped query filter in `Data/JobTrackerContext.cs`.
#### Fix
- `GetHistory(...)` now checks whether the requested job exists in the current users scoped `JobApplications` query and returns `404` if it does not.
- `JobEvent` now has an owner-scoped query filter tied to `JobApplication.OwnerUserId`.
- Added focused regression test:
- `JobTrackerApi.Tests/JobApplicationsAuthorizationTests.cs`
#### Replay after fix
Observed post-fix response:
- `GET /api/jobapplications/1/history` as Bob
- `404 Not Found`
#### Verdict
**Fixed.**
## Automated Evidence
### Focused regression test
```bash
dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --filter JobApplicationsAuthorizationTests
```
Observed:
- passed
- verifies `GetHistory` returns `NotFound` for another users job
## Final Assessment
For the prioritized raw-id authorization seams exercised in this milestone:
- **confirmed and fixed:** `GET /api/jobapplications/{id}/history`
- **no finding in this fixture pass:** attachments, correspondence, primary job read/update, follow-up patch, timeline, tailored draft, follow-up draft
## Remaining Boundary
This report covers the endpoints actually exercised in the hostile fixture pass. It does **not** claim that every authorization-sensitive route in the application has been exhaustively proven safe; it closes the high-risk raw-id seams prioritized from the earlier assessment with a real two-user runtime and replay evidence.