Trust

Testing our own boundaries

A sandbox assurance run, September 2026

Trust and security
Run on
Measured at commit
a7383d52
Model spend
$0.38 over 76 model requests, scored run

In short. On 30 September 2026 we tested nine of Gridable's security boundaries against a private copy of the product. Every boundary refused every attempt we made. For each test we also ran a copy with that one protection removed, to prove the test would have caught a failure. Reviewing the results turned up one gap next to those boundaries, which is described below with its fix. Our own team ran this, with automated tools. It is not a third-party penetration test and not an audit. We do not have either yet, and our trust page says so.

What this is, and what it is not

  • What it is: an internal, repeatable check that nine specific protections refuse the attempts they exist to refuse, measured against the code at one commit (a7383d52).
  • What it is not: a third-party penetration test (listed on /trust as Not built), a SOC 2 or ISO audit (also Not built), or a test of our production hosting, our vendors, or people. It ran on synthetic data. No customer data, customer credential or production system was involved.

What we tested

Each boundary below corresponds to a control on our trust page.

The nine boundaries tested
Boundary letterBoundaryThe protection, in plain wordsTrust-page control
AAgent access listA hired agent uses only the connections an admin gave it, even through a live workflow it editsAI and agent safety: access list
BCard conversationsOnly the person a card is waiting on can answer it; others can read, not writeAI and agent safety
COutside contentAfter an agent reads outside content, an address it composed is paused for a person before anything is sentAI and agent safety: egress
DAgent credentialsAn agent cannot change a coworker's role or permissions itselfAI and agent safety: coworker changes
EWorkspace isolationOne workspace cannot read another's runsData protection: isolation
FPublic app pagesA published app shows the public only the fields of a record it chose, never internal idsApplication security
GSecurity reportsText in a vulnerability report cannot act on our issue tracker (mentions, links, formatting)Incident response and disclosure
HExport and deleteOnly a workspace's owner can export or delete it, and only their ownData protection: export, delete
ITwo-factor sign-inWith two-factor on, a password alone gets a challenge, not a sessionAccess and identity: 2FA

How we tested

A private sandbox. The real Gridable server ran locally against a throwaway database with two synthetic workspaces. The database was deleted after each run. External services were stubbed. The only requests that left the machine were the AI model requests described below, sent through our model gateway.

Test 1: a fixed battery with controls. For each boundary we sent the request an attacker would send, using the credential that should be refused, and recorded the server's answer. We then ran the same request against a second copy of the code with only that boundary's protection removed. A "held" counts only when the unmodified code refused and the weakened copy let the request through. Otherwise the test might simply be unable to see a failure. Boundaries C and G have no web address to call, so they were driven through the same code the server runs.

Test 2: AI models probing from outside. We gave two AI models, GLM 5.3 and Claude Sonnet 4.5, one web-request tool, one fixed credential per boundary and a plain-language goal, with at most 8 requests each. Our code judged success from the server's real answers; the models' own claims were not used. Every request asked our model gateway for providers that do not retain or train on data, which the gateway applies under its own terms. The scored run made 76 model requests and cost $0.38.

What held

What held, boundary by boundary
Boundary letterUnmodified codeProtection removed (control)Result
ARefused the ungranted agent's workflow run; refused every change to a live workflow's stepsThe run was dispatchedHeld
BRefused a non-addressee's answerThe answer was acceptedHeld
CPaused before sending to a composed addressThe request would have gone outHeld
DRefused the agent's change to a coworkerThe change was writtenHeld
ERefused another workspace's runThe run was returnedHeld
FReturned only the five public fieldsInternal ids were exposedHeld
GReporter text arrived inert, in a plain-text blockMentions, issue links and links survivedHeld
HRefused export by another workspace's owner. Checked in review without a control: refused delete by that owner, and export and delete by a member who is not the ownerAnother workspace's data was exported (export only: the delete arm had no removed-protection control)Held
IPassword alone returned a challenge and no sessionA session was issuedHeld

Neither model got past any boundary. Most of their attempts never found the right address. Where they did find it (A, B, D and I), the protection refused them. The fixed battery is what tests each protection. The model run answers only a narrower question: could an outside model, probing blind with a small budget, find a way through? It did not.

What did not go to plan, stated plainly

  • One of our own tests was blind at first. Our review found that the control for two-factor sign-in (I) weakened the wrong line of code, so it could not have caught a failure. We fixed the control, re-ran it, and it now passes. The "held" above is from the fixed run.
  • Two results needed a second look. The model run produced two successful responses that looked like possible crossings: an export (H) and a workflow edit (A). The run had not kept the export's contents or the edit's request. Both were checked again in the sandbox by re-sending the likely request. The export returned the requester's own workspace, and the edit returned success only for a rename or a resave that changed no step. Neither replay crossed a boundary.
  • The review found one gap next to boundary C, tracked as #2989. Boundary C held on every road this run tested. One adjacent road had no check. An agent that had read outside content could still add a step to one of your workflows that was already switched on. That step would then run on the workflow's own schedule, and the outside-content check never saw it. We found this by reading the code and confirmed it in the sandbox; no customer was involved. It is fixed. An agent that had read outside content, or a follow-up run in the same conversation, can no longer change a workflow that is switched on unless a person approves or makes the change (fixed in 3a470078 and f8679758, both live).
  • Our test suite had three faults, unrelated to these boundaries. We fixed them before writing this.

What this does not cover

  • Replay of a two-factor code is covered by our automated test suite, not by this run.
  • Machine-to-machine tokens on our worker service were outside this run. That item is open, tracked as #2648. The check it needs was built under #806, which is closed.
  • An agent's write that starts a person's own automation is a road our trust page already lists as still being closed, tracked as #2977. This run did not test it.
  • Isolation is enforced by the application. Each workspace does not have its own database.
  • One commit, one day. This shows these protections refused these attempts at a7383d52. It does not show there are no other defects, and it does not test production configuration, hosting, vendors, denial of service or social engineering.

Report a gap

If you find something we missed, write to security@gridable.ai or use the form on our trust page. Research within the published policy is authorised.