CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/cross-tenant-data-leak-tests

Workflow-driven skill that plans and implements the cross-tenant leak-test suite - from surface inventory to the runtime CI gate a multi-tenant codebase must pass on every PR. The planning section inventories tenant-bearing surfaces (tables, APIs, object storage, search, queues, caches), classifies each by isolation model (silo / pool / bridge, per references/isolation-models.md), and derives the OWASP WSTG-ATHZ-02 coverage matrix. The battery defines the canonical test patterns (read-other-tenant-by-id, list-leak, spoofed-tenant-id-in-body, JWT-replay, FK-cross-tenant, unique-collision side channel, object-storage IDOR, search-index-direct-query, async-job-context-reload, cache-key-collision), the 404-vs-403 disclosure trade-off, the Postgres-RLS-direct patterns, and the CI integration (non-superuser non-BYPASSRLS role, fail the build on any leak). Use when designing or implementing a tenant-isolation test suite, adding the CI gate to an existing project, or investigating a leak finding.

90

1.05x
Quality

90%

Does it follow best practices?

Impact

94%

1.05x

Average score across 3 eval scenarios

SecuritybySnyk

High

Do not use without reviewing

Overview
Quality
Evals
Security
Files

criteria.jsonevals/scenario-3/

{
  "context": "An isolation suite that passes for four separate reasons unrelated to isolation: the session sets crossTenant true so the scoping branch is bypassed entirely, one repository instance is shared across all tests so a void in one leaks into the next, both tenants use the identical invoice id inv_1 so a cross-tenant hit is indistinguishable from a correct one, and every assertion is a count or a not-null check. Predicted baseline failure: the agent spots the privileged flag - it is the most visible defect - fixes that alone, and leaves the colliding ids and the shared repository in place, producing a suite that is better but still cannot localise a leak.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "Both deliverables produced",
      "description": "A file named isolation-suite-findings.md exists, and src/billing.isolation.test.js has been rewritten rather than left as found.",
      "max_score": 6
    },
    {
      "name": "Privileged session identified as the primary cause",
      "description": "The findings state that crossTenant true on the shared session makes scoped() return every invoice regardless of tenant, so the tenant predicate is never reached and removing it changes nothing. Omitting this scores zero on this criterion.",
      "max_score": 24
    },
    {
      "name": "Colliding identifiers identified",
      "description": "The findings state that both tenants seed an invoice with the id inv_1, so a lookup that crosses the boundary returns a plausible record and cannot be distinguished from a correct one. A findings document that mentions only the privileged flag scores zero here.",
      "max_score": 18
    },
    {
      "name": "Shared mutable repository identified",
      "description": "The findings state that the repository is constructed once at module scope and mutated by the void test, so test order affects results and cleanup never happens.",
      "max_score": 14
    },
    {
      "name": "Rewritten suite uses unprivileged per-tenant sessions",
      "description": "MUST NOT assert isolation through a privileged session. The new tests build a session per tenant without crossTenant, and any privileged session that remains is used only as an explicitly labelled control, never as the actor in a boundary assertion. A rewritten suite still asserting isolation through crossTenant scores zero.",
      "max_score": 16
    },
    {
      "name": "Rewritten suite would fail if the predicate were removed",
      "description": "For each of listInvoices, getInvoice and voidInvoice there is an assertion that a session from one tenant cannot reach the other tenant's invoice - and for voidInvoice, that the other tenant's record is still not voided afterwards. Score proportionally across the three operations; a suite covering only listing scores at most a third.",
      "max_score": 14
    },
    {
      "name": "Fixture rebuilt per test with distinct identifiers",
      "description": "MUST NOT keep the shared instance or the colliding ids. Each test constructs its own repository, and the two tenants' invoices carry different id values.",
      "max_score": 8
    }
  ]
}

SKILL.md

tile.json