Files
jobtrackingapp/docs/audits/evidence/two-user-isolation.md
T

3.5 KiB

Two-user isolation evidence

Captured: 2026-08-02

Scope: disposable local SQLite environment only. User A and User B used synthetic @audit.invalid identities. No production data or credentials were used.

Results

Resource or operation UI level API direct-ID test Service/query protection Result
Jobs Browser blocked A 200; B 404 for A's job; B list 0 Explicit owner predicates and global JobApplication filter Pass at API/data-query levels
Companies Browser blocked B 404 for A's company; B list 0 Explicit owner predicates and global Company filter Pass at API/data-query levels
Correspondence Browser blocked B list for A's job returned 0; copied ID returned 404 Filter through owned JobApplication navigation Pass at API/data-query levels
Attachments Browser blocked A upload/list/download 200; B job access and copied attachment download 404 Owned-job query before file operation Pass at API/data-query levels
Career Profile Browser blocked B's current-profile request 404 Current-user lookup plus owner query filter Pass at API/data-query levels
CV variants Browser blocked Copied A variant ID returned 404, but B's own list returned 500 Owner predicate/filter exists; list blocked by SQLite translation Partial: protection inspected and direct ID passed; list broken
Application workspace Browser blocked B copied A ID returned 404; A request returned 500 Owner predicate exists; owner path blocked by SQLite translation Partial
Checklist Browser blocked B copied A job returned 404; A 200 Owner predicate on job/items Pass at API/data-query levels
Timeline Browser blocked Both users received 500 Ambiguous route selection occurs before authorization logic Blocked by endpoint defect; no exposure observed
Interview preparation Browser blocked Both users received 500 Ambiguous route selection occurs before authorization logic Blocked by endpoint defect; no exposure observed
AI results Browser blocked History endpoint returned 500 Owner predicates and query filter exist Blocked by SQLite translation
Settings/session Browser blocked B /auth/me returned only B Identity/session-bound current user Pass at API level
Administrative operation Browser blocked B request returned 403 [Authorize(Roles = "Admin")] Pass at API level
Email threads/provider data External providers not connected Local correspondence passed; provider-specific IDs not live-tested Owner-scoped connection and correspondence queries inspected Code-inspected/partially tested

Protection layers observed

  • UI: protected routes require an authenticated shell, but hiding was not counted as authorization.
  • API: controllers use explicit local-auth or admin authorization attributes.
  • Service: important reads carry OwnerUserId or owned-parent predicates.
  • EF: global filters deny on null current user and match owner IDs.
  • Database: tenant ownership is primarily enforced in application queries; many owner columns are not foreign keys to AspNetUsers, so database constraints alone do not provide tenant isolation.

Limitations

  • The in-app browser control client was missing, so UI navigation as A/B was not performed.
  • Timeline/interview and several CV/AI paths failed before an ownership result could be observed.
  • No Gmail, Microsoft Graph, IMAP, Stripe, cloud AI, or remote object storage was contacted.

No cross-user disclosure was confirmed in the paths that returned a meaningful result.