Technical write-up · ToolJet
Cross-workspace ToolJet DB authorization bypass
How ToolJet DB applied workspace administrator permissions outside their authorized workspace, and how explicit workspace validation restored the boundary.
The scope of an administrator
ToolJet DB provides database tables for applications within a workspace. My research question was whether permission to manage those tables remained bound to the workspace that granted it. Consider Mallory, an administrator in Workspace A, and Alice, who manages Workspace B. Mallory has legitimate administrative powers in A; Alice’s tables remain outside that authority. The finding concerns Mallory’s own authenticated account, not a stolen Alice session.
My original local assessment covered ToolJet CE v3.20.188-lts and v3.20.189-lts and demonstrated that this boundary could be crossed. ToolJet’s published report lists CVE-2026-73068 and rates the finding Moderate 6.8 under CVSS 3.1.
The runtime observations below come from that original assessment. The comparison with the released correction is a later source review; no new vulnerability reproduction or patched-release runtime test was performed for this article.
Following the workspace boundary
I compared what the permission checks established with which resources the table operation could affect. The checks recognized the caller’s role in their current workspace. Table management, however, did not require the workspace it affected to match that authorized scope. Authority established for A could therefore be applied to B. This mismatch is the cause described in the public report.
The useful distinction is between three responsibilities. Authentication establishes the caller’s identity and workspace context. Feature authorization decides whether that caller may perform a kind of operation. Workspace validation binds the resource scope to the context in which that permission was granted. A valid administrator can pass the first two checks without answering the third question.
This is why simply finding an authentication guard was not enough to dismiss the report. Nor would removing the feature check be a valid repair: belonging to the right workspace does not by itself grant table-management permissions. The correction must retain both the workspace relationship and the action-specific authorization.
Evidence and alternative explanations
I reproduced the behavior in a local Docker environment using a disposable marker table. The preserved results for both assessed versions agree on the following outcomes; the same observations appear in the published evidence summary.
| Observation | Recorded result | What it establishes |
|---|---|---|
| Ordinary workspace access | Switching to B returned 401; B was absent from the caller’s returned workspace list. |
The normal workspace interface did not grant the account access to B. |
| Marker creation | 201; the marker count in B was 1. |
The operation changed protected state, not merely its response status. |
| Independent view | An authorized administrator’s view returned 200. |
The marker was visible from the workspace where it was created. |
| Marker removal | 200; the marker count in B returned to 0. |
The unauthorized operation could also remove the protected resource. |
The denial matters because an already-authorized administrator would not demonstrate a boundary violation. The workspace list supports that control, but is not an independent audit of all membership storage. The protected state is the decisive second half: a successful response alone would leave open whether anything changed, or whether the operation affected only A. The marker’s presence and removal in B rule out those explanations in the local test.
Impact and limits
The demonstrated starting position was an authenticated workspace administrator who knew the other workspace’s identifier. Creating and deleting tables crossed the integrity and availability boundary; the report also documents exposure of table metadata. It does not establish customer-data exfiltration, unauthenticated access, or remote code execution. The assessment used local targets, and deployment prevalence was not measured. Public impact and limitations.
Restoring the relationship
The public correction makes the missing relationship explicit. The following focused comparison shows the guard declaration in server/src/modules/tooljet-db/controller.ts, from v3.20.206-lts to v3.20.207-lts:
- @UseGuards(JwtAuthGuard, FeatureAbilityGuard)
+ @UseGuards(JwtAuthGuard, OrganizationValidateGuard, FeatureAbilityGuard)
The original declaration is also present in the inspected v3.20.188-lts source. These links pin the excerpts to immutable release commits: v3.20.188-lts declaration, v3.20.206-lts declaration, and v3.20.207-lts declaration.
In v3.20.207-lts, OrganizationValidateGuard.canActivate in server/src/modules/app/guards/organization-validate.guard.ts makes this comparison:
const request = context.switchToHttp().getRequest();
const { organizationId } = request.params;
const user: User = request.user;
return user.organizationId === organizationId;
Here, user.organizationId represents the authenticated workspace context, while organizationId identifies the requested scope. The equality check requires those scopes to agree. It sits alongside authentication and feature authorization rather than replacing either. This small guard is not the entire authorization policy; it depends on the surrounding authenticated request context. Released guard implementation.
This is an excerpt from the vendor’s correction, not a patch I authored or a representation of its complete scope. Upstream PR #17298 changes both the controller and feature-ability code. The official v3.20.207-lts release, published August 4, 2026, explicitly includes that PR. The release claim here is source-verified, not independently runtime-verified on the patched release.
For a regression suite, I would check the following conditions. These are proposed tests, not executed results or a claim about upstream test coverage.
| Proposed case | Required behavior |
|---|---|
| Authorized role, matching workspace | Preserve legitimate table administration. |
| Authorized role in A, resource scope B | Reject access and leave B’s protected state unchanged. |
| Matching workspace, insufficient role | Reject the action despite the workspace match. |
The two original runtime-tested versions and the three source snapshots establish specific observations, not the first introduction or a complete affected-version range. Other releases and backports were not individually assessed here. The remaining verification step is to run regression coverage against the released correction and confirm both rejection and unchanged protected state.