Synthetic assessment — demonstration only

Inside a Liquid security report

Explore Liquid’s synthetic expense-app assessment with evidence, developer fix instructions and retest outcomes.

Northwind Expenses (synthetic sample) · staging.northwind-expenses.example

LQ-01 · High

Staff can read any employee's expense by changing its ID

Evidence

Original synthetic evidence and records.

GET /rest/v1/expenses?id=eq.1042 as staff@test.example → 200, owner_id ≠ caller. Policy expenses_select uses auth.role() = 'authenticated'.

Fix plan

In Supabase, update the SELECT policy on public.expenses so Staff can only read rows where owner_id = auth.uid(), and Managers can read rows where team_id matches their team via a security-definer has_role check. Do not change other tables.

Retest outcome

Fixed — Retest 14 Oct 2026: request returned 0 rows for Staff; Manager access intact.

LQ-02 · High

Staff can approve expenses through the API

Evidence

Original synthetic evidence and records.

POST /functions/v1/approve-expense {id:1051} as staff@test.example → 200, status changed to approved.

Fix plan

In the approve-expense function, verify the caller has the manager role using the user_roles table before updating. Return 403 otherwise. Hiding the button is not enough.

Retest outcome

Still present — Retest 14 Oct 2026: role check added in UI layer only; API still accepted Staff approval.

LQ-03 · Medium

Receipt share links work without signing in and never expire

Evidence

Original synthetic evidence and records.

Bucket 'receipts' public = true. Object URL fetched without auth → 200.

Fix plan

Make the receipts storage bucket private and serve receipts via signed URLs with a 10-minute expiry, generated only for users allowed to view the related expense.

Retest outcome

Awaiting retest

LQ-04 · Low

Team export result could not be confirmed for Staff

Evidence

Original synthetic evidence and records.

Export job exceeded 120s runner budget for both accounts. No response body captured.

Fix plan

Investigate why the monthly export job exceeds two minutes in staging with synthetic data. Confirm the export endpoint checks the manager role server-side.

Retest outcome

Awaiting retest

LQ-05 · High

Expense assistant lets Staff trigger the approve tool

Evidence

Original synthetic evidence and records.

Assistant tool approve_expense executed for a Staff session. Tool definition has no role requirement; server key used for the update.

Fix plan

In the assistant's approve_expense tool handler, run the update with the signed-in user's session (not the service key) and verify they have the manager role via has_role before executing. If not, return a refusal to the model. Apply the same rule to every tool that changes data.

Retest outcome

Awaiting retest

Review coverage

  • Sign in and session expiry — No issue observed
  • View own expenses — No issue observed
  • View another employee's expense — Evidence
  • Approve an expense — Evidence
  • Upload a receipt — No issue observed
  • Export monthly report — Inconclusive
  • Shared receipt link — Evidence
  • Browser bundle secrets — No issue observed
  • Slack notification integration — Not tested
  • Payroll sync — Blocked