8000 Tags · ToolJet/ToolJet · GitHub
[go: up one dir, main page]

Skip to content
< 7FFF link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.4af22a99b464e505.module.css" />

Tags

Tags

v3.21.95-beta

Toggle v3.21.95-beta's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Fix: SSRF hardening with an EE protection toggle and allowlist (#18600)

* Fix: harden SSRF protection across data-source connectors and OAuth

* Feature: honour SSRF runtime config in built-in plugin check

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: exclude common package tests from tsc build

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: honour SSRF runtime config in marketplace plugin check

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: handle all:true in SSRF-safe DNS lookup

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: honour SSRF runtime config in server helper, scope test connection

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: handle all:true in SSRF-safe DNS lookup

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: SSRF instance settings and EE runtime publisher

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: SSRF settings endpoints for super admins

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: ungate SSRF settings routes from licence check

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: SSRF toggle and allowlist on Security page

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: one-time SSRF protection notice for super admins

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: link SSRF notice to /settings/security

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Docs: SSRF runtime config context and release note

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: keep plugin tests out of the plugins build

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: split Security page into sub-tabs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: keep plugin tests out of the plugins build

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: add Security page heading

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: Security tab content spacing

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test: run marketplace SSRF tests from plugins jest

marketplace/ has no Jest runner, so the marketplace common SSRF suite never
ran. The plugins Jest config now also roots at marketplace/plugins/common.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: block bracketed IPv6 literals in built-in SSRF check

new URL() keeps the brackets on IPv6 hostnames and rewrites IPv4-mapped
addresses to hex ([::ffff:7f00:1]), so the built-in copy's private-IP check
missed [::1], [fd00::1], [fe80::1] and [::ffff:169.254.169.254], and Node
skips the lookup hook for IP literals. The hostname is now unbracketed before
the private-IP, allowlist and DNS steps (async and sync checks), and
isPrivateIPv6 decodes the hex IPv4-mapped form, as the marketplace copy does.

The bracket strip applies on every edition: it is a parsing bug, not a policy
change, and CE users who opt in to SSRF protection are equally exposed.

Also, under the EE runtime config a hostname with no DNS answer is now
blocked (fail closed), matching the marketplace and server copies. IP
literals skip DNS. Without the runtime config the empty answer still fails
open, so CE/Cloud are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: check blocked schemes before the SSRF allowlist in plugin copies

Both plugin copies returned on an allowlisted host before the scheme check,
so gopher://jira.corp or ftp://10.0.4.12 passed once the host was
allowlisted, while the server copy rejects them. An allowlist entry vouches
for an address, not for a dangerous scheme.

The built-in copy only has an allowlist under the EE runtime config, so the
reorder is unconditional there. The marketplace copy also exempts loopback
names by default on CE, so it checks the scheme early only when the runtime
config is present, keeping CE/Cloud byte-identical. Same order in both sync
checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test: cross-copy SSRF parity cases

The same table now runs against all three SSRF check copies with the runtime
key present: bracketed IPv6 loopback, ULA, AWS IMDSv6, IPv4-mapped loopback
and metadata, and link-local literals are blocked; a hostname resolving into
an allowlisted CIDR and an allowlisted IPv6 literal pass. Dropping the
allowlist exemption from the DNS step now fails the server and marketplace
suites.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: keep test-connection URL checks for every connector

Scoping the test-connection SSRF check to a list of HTTP kinds dropped it for
every kind not on the list (s3 endpoint, qdrant url, woocommerce host, every
marketplace plugin) on all editions. The URL-style option check now runs for
every kind again, and the host/port/protocol check runs for every kind except
a deny-list of built-in database drivers, which is never applied when the
request carries a plugin_id (that picks a marketplace plugin whatever kind
says).

The non-http protocol test now mocks DNS and asserts the call resolves, so it
fails if the protocol coercion is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Docs: describe runtime-config SSRF behaviour in server helper comments

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: drop redundant close icon from SSRF notice

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: always enforce SSRF protection on Cloud in every check

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: fail closed on empty DNS answers on Cloud

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: classify IPv6 addresses by their embedded IPv4 in every SSRF check

IPv4-mapped (any spelling), SIIT, IPv4-compatible, NAT64, 6to4 and Teredo
addresses are now judged by the IPv4 they carry, and ::, all of fe80::/10,
fec0::/10 and ff00::/8 are blocked. Bracketed IPv6 literals are classified
without brackets in the marketplace and server copies; under the runtime
key and on Cloud a literal skips the DNS step, so public ones are allowed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: treat NAT64 local-use prefix as non-public in SSRF checks

64:ff9b:1::/48 can carry its IPv4 at any RFC 6052 offset, so decoding
the last 32 bits let 127.0.0.1 hide behind a public-looking tail. The
whole prefix is now blocked by every policy; 64:ff9b::/96 still decodes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: stop the SMTP connector reading local files or URLs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: keep SMTP test out of build and accept address objects

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: stop OAuth token exchange following redirects and pin the checked IP

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: resolve relative redirects before SSRF validation

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: note that public apps can reach allowlisted addresses

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: classify hosts-file names against the SSRF allowlist

resolve4/resolve6 never read /etc/hosts, so under the EE runtime config a
hosts-file-only name was blocked even when its address was allowlisted.
When DNS returns nothing, the three SSRF copies now fall back to
dns.lookup and classify those addresses; CE and Cloud are unchanged.

Also fixed the plugins and marketplace lint failures (prettier, and
TypeScript tests now ignored like the JS ones).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: limit the test-connection database-kind skip to EE

CE and Cloud check the host of built-in database kinds again, as before
this branch; only EE with the SSRF runtime config skips them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Docs: correct Cloud SSRF behaviour and SMTP address note

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: accept underscores inside SSRF allowlist hostnames

Docker Compose service names such as my_service are now valid entries;
a leading or trailing underscore is still rejected. Bumps frontend/ee for
the matching client check and the banner-only-when-enabled fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Chore: log progress in the SSRF settings data migration

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: show SSRF allowlist as a scrollable table

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci: disable SSRF protection in Cypress Marketplace runs

* feat: rename SSRF protection to Private network access in the UI

* feat: explain private network blocks and where to allow them

Every block now names the host, says why (private address, resolves to
one, or could not be resolved, keeping the resolver's own error), and on
EE points to Settings → Security → Private network access. Same wording
in all three copies of the check.

* fix: show private network block reasons in HTTP connector errors

REST API, GraphQL, OpenAPI, n8n, Confluence and ServiceNow wrapped every
request failure as "Query could not be completed", hiding why a redirect
or connect-time lookup was blocked. Blocks now keep their own message;
other failures are unchanged.

* feat: rename Private network access to Outbound requests

* feat: leave SSRF protection off by default in dev mode

The toggle is now seeded unset. Unset means off when the server runs
with NODE_ENV=development (npm run start:dev) and on everywhere else; an
explicit choice from the Security page always wins.

* feat: keep SSRF protection as it was on existing setups

The settings migration now tells a new installation (no workspace yet)
from an existing setup. New installations get protection on by default;
existing setups keep their current behaviour: off, or on if they had
opted in with SSRF_PROTECTION_ENABLED=true.

* feat: show the SSRF dashboard notice on new installations only

* test: pin that a toggle turned off in the UI wins over SSRF_PROTECTION_ENABLED

* test: cover every SSRF toggle default and upgrade case

* fix: make the SSRF settings migration self-contained

CI now rejects migrations that import project code. The migration uses
raw SQL instead of entities and constants, and relies on the unique key
(ON CONFLICT DO NOTHING) so a re-run never overwrites a stored value.

* test: don't assume one localhost entry in the all:true lookup test

* fix: restore edition-aware SSRF defaults in the plugins check

The plugins and marketplace copies of the outbound request check are now identical, with a test that fails if they drift. CE is on by default again (loopback and metadata blocked, RFC1918 and localhost allowed), EE stays opt-in without the runtime config, Cloud is always on. Also bumps server/ee for the SAML picture check.

* refactor: move SSRF settings into their own ssrf module

The outbound requests settings API, its feature keys and setting keys move
out of instance-settings into a new ssrf module, so instance-settings is back
to its pre-SSRF state. AppModule only loads the ssrf module outside the
migration app context: its runtime config publisher reads instance_settings
on boot, which waited forever on the migration transaction's own lock and
hung db:reset and fresh EE installs. The module also leaves the publisher out
if it is ever imported there. Tokens cannot reach the new module.

* chore: update submodule pointers

* fix: give the SSRF settings data migration a real down()

The migration authoring rules from the release line require every newer
migration to undo up() or say why it cannot. down() now removes the three
rows up() adds; the SSRF code reads missing rows as unset.

* ci: disable SSRF protection in App Builder Cypress seeding

* ci: skip the Cypress SSRF seeding step when the API is missing

* adding submodule commit

* test: bypass the SSRF check in the test-connection binding spec

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: gsmithun4 <gsmithun4@gmail.com>

v3.20.257-lts

Toggle v3.20.257-lts's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Release v3.20.256 lts (#18945)

* Bump version to 3.20.256-lts across all components

* Auto-start trial for new users (#18828)

* feat: skip auto trial and add trial_claimed_at to users

* fix: tighten Cloud trial eligibility, skip auto-trial in tests

- Bump server/ee and frontend/ee for the trial eligibility fixes
- Jest: default DISABLE_AUTO_TRIAL=true so setup-super-admin doesn't call the license server
- Shorten trial-related comments

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* chore: update submodule pointers (#18935)

* Feature: Land new users on the home page prompt after onboarding (#18961)

* feat: skip auto trial and add trial_claimed_at to users

* feat: send verified signups to the workspace home page

On EE and cloud, a signup that skips the onboarding questions now lands on
/<workspace>/home (the AI prompt) instead of the dashboard. CE and an explicit
redirectTo are unchanged. Marks the sample onboard app endpoint as unused.

* chore: update submodule pointers

* chore: bump frontend/ee to merge release/v3.20.256-lts

---------

Co-authored-by: Siddharthpl <siddharthpundir73@gmail.com>

* Auto trial bug fixes (#18975)

* chore: update frontend/ee for onboarding step 3 image fix

* fix: report the license's own type after expiry

Expired licenses are reported as basic, so the frontend couldn't tell an
expired trial from an expired paid license. Add termsType to the license
status and bump frontend/ee for the nav bar fix.

* chore: drop lint-only reformatting from the release merge

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: update frontend/ee pointer

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Update first-user onboarding spec for home-page landing (#18976)

Onboarding no longer shows the free-trial page or the sample-app step
(#18961, ee-frontend#870); after the workspace step the user lands on
/my-workspace/home. Assert that landing and the home prompt header
instead, and set retries to 0 since first-user setup is one-shot.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* bump version to 3.20.257-lts across all components

---------

Co-authored-by: Siddharth Pundir <145639697+Siddharthpl@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Muhsin Shah C P <muhsinshah21@gmail.com>
Co-authored-by: Siddharthpl <siddharthpundir73@gmail.com>
Co-authored-by: Ajith KV <ajith.jaban@gmail.com>

v3.21.94-beta

Toggle v3.21.94-beta's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Release v3.21.80-beta (#18561)

* fix: guard organization invite acceptance against identity mismatch

acceptOrganizationInvite() now verifies the logged-in caller's email matches
the invite's target user before proceeding, mirroring the existing pattern
in activateAccountWithToken.

Covered by a unit test on the service-level guard and an e2e test on the
full HTTP pipeline.

* chore: bump frontend ee subm and sync skills

* fix: tighten self-hosted workspace-signup password handling for existing accounts

whatIfTheSignUpIsAtTheWorkspaceLevel() now only takes the instant-activation
fast path when the existing account already has a password set. Accounts
without one fall through to the existing invite-email flow instead.

Covered by unit tests on the service-logic guard and e2e tests on the full
HTTP pipeline.

* fix: require a configured client ID before verifying Google OAuth tokens

GoogleOAuthService.signIn now rejects sign-in when the SSO config has no
clientId, instead of calling the underlying library with an undefined
audience. Applies to both editions.

Covered by unit and e2e tests.

* fix: respect the configured signup setting on instance-wide SSO login

OauthService.signIn no longer falls back to always allowing signup for
instance-wide SSO logins; it now reads the same enableSignUp value used
everywhere else in the flow.

Covered by a unit test. E2e coverage for this specific path is blocked by a
pre-existing, unrelated test-infrastructure issue, tracked separately.

* fix: scope avatar file access to owner or same-org admin/builder

* fix(deps): remediate high-severity Dependabot alerts in server (#5448)

* fix(deps): remediate high-severity Dependabot alerts in root (#5447)

* fix(deps): remediate high-severity Dependabot alerts in cli (#5440)

* fix: patch adm-zip DoS vulnerability in plugins (GHSA-7q85-xj36-vmfc)

adm-zip is pulled in transitively via ibm_db, which pins it below the
patched 0.6.1 release. Add an override in plugins/package.json to force
resolution to 0.6.1 regardless of ibm_db's declared range.

* fix: scope User entity queries to safe fields (GH #17717)

group-permissions' list-users-in-group endpoint returned unfiltered
User rows (password hash, invitation/reset tokens) nested in the
GroupUsers response; scoped the query to safe fields and added a
strict response DTO with ClassSerializerInterceptor. Hardened several
other unselected User queries in profile, app-permissions and
group-permissions repositories that don't currently reach a response
but were over-fetching sensitive columns unnecessarily. Updated the
group-permissions e2e test to assert the new response shape.

* chore: bump submodules

* fix: scope app-environments lookups to the caller's workspace

Verify that the version, app and environment ids sent to init, post-action,
the environments list and the versions-by-environment endpoint belong to the
caller's workspace before use, and reject a missing app_id on the versions
endpoint instead of matching every app.

Adds two-workspace e2e and unit specs and a module AGENTS.md.

* chore: bump submodules

* test: cover the CE app-environments workspace-scoping paths

Run the two-workspace e2e spec against both editions, since the EE service
overrides init, post-action and the list without calling the CE versions.

* test: cover post-action with an app and environment from another workspace

* fix(data-sources): stop test-connection from leaking secrets to attacker-chosen hosts for use-only users

* test(data-sources): cover test-connection credential/secret binding regression

* fix: scope folder_apps create/delete to the caller's workspace

The folder_apps create/bulkCreate sinks resolved and moved a binding by
app_id alone, with no organization_id in scope, and the ability factory
granted admins CREATE/DELETE unconditionally. An admin — or a folder owner
via the bulk app_ids path — could therefore bind another workspace's app
into their own folder, disclosing the app's metadata and detaching it from
the victim's folder.

The ability guard now rejects any folder_apps mutation whose target folder
or target app does not belong to the caller's workspace, for every role
including admins. The create/bulkCreate sinks additionally assert app
workspace membership as defense in depth.

Advisories: GHSA-m46f-vj4w-2cpw, GHSA-mg7j-56p8-p2m2,
GHSA-r2hw-m6w2-vmq7, GHSA-v675-3qmh-6rmf

* chore: update server/ee submodule pointer

* fix: authorize resource export

Resource export now only operates on the caller's own workspace: a request
whose organization_id differs from the session workspace is rejected, and
ToolJet Database tables are always resolved against the session workspace
rather than the id supplied in the body.

Exporting an app additionally requires view access to that app (admin,
super admin, all-apps view/edit, or the app in the user's viewable or
editable set). App-create alone still grants import, and exports without
an app keep their previous behaviour.

* test: expect 403 when exporting an app with app-create only

Export now requires view access on the app, so a developer whose only
grant is app-create is denied. Admin export still succeeds.

* fix: require a live session to list workspaces and disable unused TJDB join route

The workspace list guard no longer treats the user as optional, so the
session is validated while users can still switch away from archived
workspaces. The TJDB join endpoint has no callers since join queries run
server-side, so it is disabled.

* fix: remove unused ToolJet DB join endpoint

The HTTP join route had no callers; app join queries run in-process.
Drop the route with its DTO, exception filters, feature key and the
dead frontend service call. Add e2e coverage that ToolJet DB table
routes stay scoped to the caller's workspace.

* fix(data-sources): scope OAuth base-url constant resolution to session workspace, rejecting foreign organization_id (403) and out-of-workspace environment_id (404) before resolving secrets; adds regression tests

* fix(data-sources): gate OAuth base-url endpoint to data-source configurers (admin/builder/create/configurable), returning 403 for viewers/end-users who were reaching decrypted secrets through it; adds ability unit tests

* fix(data-queries): enforce app/workspace authorization on POST /:id/run so End Users can't run queries of unshared apps

* fix(data-queries): bump server/ee for env-access guard fix (?mode=view bypass)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(data-queries): scope bulk query update to authorized version to prevent cross-app IDOR

* fix(data-queries): confine anonymous public-app query runs to the released version (GHSA-grw5-2fvf-vwm4 / grh7-xf9j-r3qg)

* fix(data-queries): confine anonymous public-app query runs to the released versi
8000
on

* fix: enforce permission check on mutations for public apps

* fix: require configure privilege to authorize shared-token OAuth2 data source

* fix: scope data-sources dependent-queries by workspace to prevent cross-tenant leak

* fix: restrict data source update to Create/Configure, not Delete-only

* Fix: restrict ToolJet-DB proxy, join and export to authorized workspace access

* Fix: drop removed JOIN_TABLES feature key from ToolJet-DB ability

* chore: point server/ee at the ee release merge with main

The main merge took server/ee from main (68e25c06), which drops the
release's ee fixes (#870, #888, #912, #965). Point it at 866316de, the
ee-server merge of main into the release branch.

* fix: connect the sample data source as a restricted role

Provision a tooljet_sample_* role on startup with SAMPLE_PG_DB_USER (or
PG_USER) and point every sample data source at it. If the role can't be
set up, sample queries are disabled instead of using the admin user.
Role setup and populate-sample-db share one advisory lock so a table
rebuild can't interrupt the grants.

* chore(deps): fix high-severity vulnerabilities in frontend dependencies (#18646)

Resolves all open high-severity Dependabot alerts for
frontend/package-lock.json and the remaining high findings from
npm audit.

- Bump axios to ^1.20.0, dompurify to ^3.4.17, postcss to ^8.5.18,
  lodash to ^4.18.1, flatted to ^3.4.4 and webpack-dev-server to
  ^5.2.7 (drops node-forge via selfsigned 5)
- Replace react-spring with @react-spring/web, removing react-native,
  metro, image-size and old ws copies from the tree
- Bump form-data peer range in plugins to ^4.0.6
- Add overrides where upstream ranges block a patched version:
  brace-expansion (minimatch@3), immutable (draft-js),
  webpack-dev-middleware (storybook builder) and serialize-javascript
- Refresh remaining transitive deps within their existing ranges

* Fix: stricter TJDB bulk writes, Python sandbox and plugin loading (#18553)

* fix: stricter TJDB bulk write column checks and Python sandbox fallback

ToolJet Database bulk update and upsert accept only existing columns and
quote column names with escapeIdentifier. Workflow Python steps are
refused when nsjail is missing unless TOOLJET_WORKFLOW_SANDBOX_BYPASS=true.

* fix: only load marketplace plugins by validated id

Remove the unused GitHub repo fetch path for marketplace plugins so plugin
code can only come from the ToolJet marketplace, and reject plugin ids that
are not plain identifiers before they are used to build download URLs or
local file paths.

* Fix/restapi metadata secret redaction security (#18701)

* fix: redact resolved secrets from query execution metadata

* fix: complete query-metadata secret redaction (EE, plugin test, spec)

Follow-on to the cherry-picked CE fix that redacts resolved {{secrets.*}}
from query execution metadata. Brings the fix to the EE path and keeps the
build and tests green:

- bump server/ee to the EE scrub commit (runQuery + resolveConstants), so
  the redaction also applies on EE/Cloud where runQuery is fully overridden
- move the redactHeaders plugin test from .ts to .js: a .ts test under the
  common package breaks its tsc -b build (file outside rootDir: lib)
- update the util.service resolveConstants call assertions for the new
  optional collectedSecretValues argument

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Pratush <pratush@Pratushs-MBP.lan>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* Security fix for main advisories

* Fix: require a password on the bundled Redis

* High vulnerabilities in plugin is resolved (#18728)

* fix: resolve high-severity Dependabot alerts in marketplace (#18705)

Regenerate the marketplace lockfile from scratch, upgrade lerna to v10
and add overrides for transitive packages pinned to vulnerable versions
(follow-redirects, zod, smol-toml, undici, tmp); raise the axios floor
to 1.20.0. Pin the hoisted @types/node to the 25 line, as on main,
because v26 types do not parse under TypeScript 4.9.

Regenerate the plugins/common lockfile so brace-expansion resolves to
1.1.21.

* Fix: Patch high-severity advisories in server dependencies (#18704)

* fix(deps): patch high-severity advisories in server dependencies

Raise minimum versions: compression, joi, undici.
Upgrade nodemailer 9 -> 10 (needs Node 20+; the server runs Node 22).

Align the Nest framework packages (common, core, platform-express,
platform-ws, websockets, microservices, testing) to 11.2.8. multer 2.4+
reworded an error message that Nest 11.1 matched on, which turned a
wrong-field upload from 400 into 500; Nest 11.2 maps by error code.
@nestjs/microservices 11.2 also does not load next to core 11.1.

Raise override floors: @grpc/grpc-js, brace-expansion, fast-uri, multer,
js-yaml. Add scoped overrides: mailparser and preview-email use
nodemailer ^10, mailparser uses linkify-it ^5.0.2 (it pins an exact
version), and postcss-parent-selector uses postcss ^8.5.18 (removes the
nested postcss 5 copy).

Refresh the lockfile for @xmldom/xmldom, body-parser, browserslist,
source-map-js and form-data, whose fixes are inside existing ranges.

Docker: install joi 17.13.8 instead of 17.4.1 in six images, so the
image no longer replaces the patched copy with the old one.

Alerts with no upstream fix are not part of this change.

* fix(deps): update node-forge to 1.4.1

node-forge 1.4.1 requires a canonical DER DigestInfo when verifying
RSA PKCS#1 v1.5 signatures. It is inside the existing ^1.3.1 range
required by google-p12-pem, so only the lockfile changes.

* chore(deps): raise joi pin in cypress test images to 17.13.8

Matches the runtime images and the server lockfile, so the test images
no longer install the old joi.

* chore: point server/ee at an existing commit

The pointer inherited from release referenced a commit that no longer
exists in the submodule remote, so image builds failed at the
submodule update step. Point it at the commit that contains the same
change on the submodule's release branch.

* fix(deps): upgrade AI SDK to v5 and zod to 4.6

zod 3 carries a high-severity advisory and the AI SDK v4 requires zod 3,
so both move together.

- Raise ai to 5.0.x, the @ai-sdk providers to 2.x and zod to 4.6.7.
- Override undici under @ai-sdk/provider-utils to 7.30.1, because v5
  pins undici 5, which has open advisories.
- Point server/ee at the matching agent node migration.

* chore: point server/ee at the agent node model lookup fix

Moves the pointer to the commit that also fixes the AI model lookup,
which asked for a relation the data source entity no longer has.

* Fix: bound Redis job retention and in-memory cache growth (#18703)

* fix: bound Redis job retention and in-memory cache growth

- Default BullMQ job retention for queues and jobs that set none, so
  finished jobs no longer stay in Redis forever.
- Add an age limit to workflow job retention; each job holds the full run
  result.
- Give in-memory cache entries a 5-minute default expiry and cap the store
  at 1000 entries, so keys that are never read again (OAuth authorization
  codes) no longer accumulate for the life of the process.

* chore: update submodule pointers

* revert: keep count-only workflow job retention

An age limit does not lower peak Redis use; the count already caps it.

---------

Co-authored-by: gsmithun4 <gsmithun4@gmail.com>

* Fix: update snowflake-sdk and lerna dependencies in package-lock.json (#18765)

* Fix/docs high dependabot alerts v3.21.80 beta (#18762)

* fix(docs): bump body-parser to 1.20.9 to resolve high-severity DoS alert

* fix(docs): bump launch-editor to 2.14.2 to resolve high-severity alert

* fix(docs): bump follow-redirects to 1.16.2 to resolve high-severity alerts

* fix(docs): bump source-map-js to 1.2.2 to resolve high-severity alert

* fix(docs): bump compression to 1.8.2 to resolve high-severity alert

* fix(docs): bump brace-expansion to 1.1.21 and 2.1.7 to resolve high-severity alerts

* fix(docs): bump joi to 17.13.9 to resolve high-severity alert

* fix(docs): bump fast-uri to 3.1.9 to resolve high-severity alerts

* fix(docs): bump image-size to 2.0.4 to resolve high-severity alerts

* fix(docs): bump js-yaml to 4.3.2 to resolve high-severity alert

* fix(docs): bump svgo to 3.3.5 to resolve high-severity alert

* fix(docs): bump nanoid to 3.3.20 to resolve high-severity alert

---------

Co-authored-by: Pratush <pratush@Pratushs-MBP.lan>
Co-authored-by: Pratush <pratush@Pratushs-MacBook-Pro.local>

* fix(cli): resolve high-severity Dependabot alerts in CLI lockfile (#18771)

Upgrade mocha from 9 to 10 so it no longer pins js-yaml 4.1.0, drop the
nanoid override that only existed for mocha 9, and refresh the lockfile
so every package flagged by Dependabot resolves to a patched version.

* Fix: Send git-sync failure notification on every failed run (#18800)

* Fix: send git-sync failure notification on every failed run

* Bump server/ee: trim git-sync dedupe fix

* fix: authorize resource export per resource type (#18848)

Export now needs create + edit on each requested resource, checked
against that type's own permissions: apps (app-create + edit),
workflows (workflow-create + edit), modules (module-create + edit).
View access no longer allows export, matching the dashboard's Export
option. Every app in the body is checked, not only the first, and ids
outside the caller's workspace are denied.

ToolJet Database table export follows the table-metadata view rule
(admin, builder or tjdb CRUD) instead of requiring app-create.

The cross-workspace table export spec now expects 201 with no table:
the controller forces the session workspace, so the foreign table is
skipped rather than rejected.

* fix: do not update invited accounts from the public instance signup path (#18851)

An invited user who goes through the public signup page now only gets the
activation link re-sent. Their account is no longer modified by that request,
so the password is always set by whoever opens the link.

Remove the unused updateExistingUserDefaultWorkspace helper and add a
regression test.

* CI: Unblock release v3.21.80-beta server build and vulnerability gate (#18875)

* chore: update submodule pointers

* fix: unblock release CI — sync server lockfile, keep CE-only scoping spec public

The server lockfile had lost the mjml/html-minifier optional dependency tree,
so npm ci failed. The workspace-scoping spec ran an EE row in the public test
tree, which check-ee-leak.sh rejects; the EE row now lives in ee/test.

* chore: update submodule pointers

* fix: clear release vulnerability gate blockers in server and plugins

Bump the plugins toml override to ^5.0.1 (snowflake-sdk, its only consumer,
already asks for ^5). Drop the unused mjml and html-minifier optional
dependencies from the server; nothing references them and html-minifier has
no patched release.

* fix: repair plugins lockfile so built plugins resolve their dependencies

The lockfile had lost the proxy-agent entry @databricks/sql needs, and had
mariadb, mysql2 and nodemailer nested under their workspace packages instead
of hoisted. plugins/dist resolves from plugins/node_modules, so server
migrations failed with MODULE_NOT_FOUND.

* fix: override basic-ftp to ^6.2.5 in plugins

Restoring proxy-agent for @databricks/sql pulled in basic-ftp 5.3.1 through
pac-proxy-agent and get-uri, which has a HIGH advisory (<=6.2.0). get-uri's
latest release still asks for ^5, so override it; every Client method get-uri
calls exists in 6.x.

* fix: override proxy-agent to ^6.5.0 for @databricks/sql

proxy-agent 8 is ESM-only. Node's require() loads it, but Jest's module
loader can't, so every server suite that loads plugins/dist failed with
"Cannot use import statement outside a module". 6.x is CommonJS and is what
@databricks/sql itself asks for; the basic-ftp override still covers its chain.

* test: give data sources distinct names in data-queries specs

Data source names are unique per workspace branch, so two apps seeded in one
workspace collided. Cherry-picked from a1ee618 (#18719), without its
import-export hunk, which passes as-is on this branch.

* chore: update submodule pointers

* test: catch CE specs up with release-line security fixes

- Route inventories: dependent-queries now uses :id, and the ToolJet DB join
  route is gone.
- ToolJet DB isolation: seed workspace B's environments (table create reads
  them), and drop the committed seed in afterAll. Its leftover workspaces have
  signup off and became the instance's oldest workspace, so later CE specs in
  the same worker got 403 on signup.

* chore: update submodule pointers

---------

Co-authored-by: Shantanu Mane <maneshantanu.20@gmail.com>

* fix: expose MessagePort and DOMException to marketplace plugins

Marketplace plugins run in a vm context built from `...global`, which only
copies enumerable properties. MessagePort, MessageChannel and DOMException
are non-enumerable in Node, so plugins bundling undici 7 (Qdrant's REST
client since the marketplace lockfile regeneration) failed at load with
"MessagePort is not defined" on every operation.

* fix(cli): resolve remaining high/critical Dependabot alerts in CLI lockfile (#18914)

Prune the stale mocha/nanoid entry left after the mocha 10 upgrade, apply npm audit fix, and override tmp and serialize-javascript.

Co-authored-by: Pratush <pratush@Pratushs-MBP.lan>

* fix: require create access to export modules and ToolJet Database tables (#18909)

Module export (POST /api/modules/export) let any builder export, even
without module-create. It now needs module-create plus edit on each
requested module, rejects ids that are not modules in the workspace, and
requires tjdbCRUD when tables are included.

ToolJet Database table export on /v2/resources/export no longer lets
every builder through; non-admins need tjdbCRUD.

* list api search params issue fixed (#18928)

* Update subproject commits for frontend and server components

* Bump version to 3.21.94-beta for all components

---------

Co-authored-by: Shantanu Mane <maneshantanu.20@gmail.com>
Co-authored-by: Pratush <pratush@Pratushs-MacBook-Pro.local>
Co-authored-by: Rudhra Deep Biswas <rudra21ultra@gmail.com>
Co-authored-by: Pratush <pratush@Pratushs-MBP.lan>
Co-authored-by: gsmithun4 <gsmithun4@gmail.com>
Co-authored-by: Pratush Sinha <104584767+Pratush613@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Adish M <44204658+adishM98@users.noreply.github.com>
Co-authored-by: Akshay Sasidharan <akshaysasidharan93@gmail.com>
Co-authored-by: Johnson Cherian <johnsonc.dev@gmail.com>
Co-authored-by: Akshay <akshaysasidrn@gmail.com>
Co-authored-by: Souvik <psouvik260@gmail.com>
Co-authored-by: Adish M <adish.madhu@gmail.com>
Co-authored-by: Ganesh Kumar <40178541+ganesh8056@users.noreply.github.com>
Co-authored-by: Rudhra Deep Biswas <98055396+rudeUltra@users.noreply.github.com>
Co-authored-by: johnsoncherian <57667706+johnsoncherian@users.noreply.github.com>
Co-authored-by: Shaurya Sharma <shaurya064@gmail.com>
Co-authored-by: Nakul Nagargade <nakul@tooljet.com>
Co-authored-by: manishkushare <kushare.manish9@gmail.com>
Co-authored-by: Vijaykant Yadav <vjy239@gmail.com>
Co-authored-by: devanshu052000 <devanshu.rastogi05@gmail.com>
Co-authored-by: ajith-k-v <ajith.jaban@gmail.com>
Co-authored-by: rudrapratik30 <pratik104agrawal@gmail.com>
Co-authored-by: Yukti Goyal <yuktigoyal02@gmail.com>
Co-authored-by: Kavin Venkatachalam <50441969+kavinvenkatachalam@users.noreply.github.com>
Co-authored-by: Arnav Maggon <arnavmaggon2005@gmail.com>
Co-authored-by: Swathi Hameed <42898362+swathihameed@users.noreply.github.com>
Co-authored-by: Shaurya Sharma <79473274+shaurya-sharma064@users.noreply.github.com>
Co-authored-by: gsmithun4 <3417097+gsmithun4@users.noreply.github.com>
Co-authored-by: Ganesh Kumar <ganesh8056234@gmail.com>
Co-authored-by: Madhav Jha <jhamadhav28@gmail.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

v3.20.256-lts

Toggle v3.20.256-lts's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
test connection issue fixed (#18835)

v3.21.93-beta

Toggle v3.21.93-beta's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Fix: App loads exhausting the DB pool via per-app hydration (#18884)

* fix: use COUNT in app license guards to avoid pool exhaustion

AppCountGuard and ResourceCountGuard loaded every App entity with
manager.find + relations just to compare the total against the license
limit. Each loaded App fires AppsSubscriber.afterLoad, which opens its
own transaction (GitSyncConfigsUtilService.getDetails + version lookup,
hitting organization_git_sync_branches). One create request therefore
held 1 outer pool connection plus N inner ones, exhausting PG_POOL_MAX
(25) once 25+ front-end apps existed and failing creates with 500
"timeout exceeded when trying to connect".

Use manager.count with the same where-condition instead. COUNT never
instantiates entities, so no subscriber runs and pool use stays flat
regardless of app count.

* fix: use COUNT in role-downgrade ownership check to avoid pool exhaustion

Same pattern as the app license guards: checking whether a user owns any
apps loaded every App entity via manager.find just for a length check,
firing per-row afterLoad work in separate transactions. At scale this
exhausts the DB pool the same way.

Use manager.count for the gate. App names for the 400 error payload are
fetched only on the error path via a raw names-only query, which never
instantiates entities. Success and ownership-transfer paths are unchanged.

* test: pin single-COUNT app counting in license guards

Add a unit spec asserting both license guards count apps via a single
manager.count call and never load entities via find. Restoring find
fails the spec. Also record the never-find-to-count-App rule in the
licensing module docs.

* fix: use raw queries for module lookups in app import/export

Two module lookups instantiated full App entities while reading only
id and co-relation-id columns, firing per-row afterLoad work in
separate transactions. Raw selects return the same rows with no
entity instantiation. Downstream readers only ever used those two
columns.

* fix: skip per-row app hydration in sample-app and import listing loads

* chore: update submodule pointers

* fix: stop per-version app hydration starving the DB pool on slug lookups

GET /api/session?appId=<slug> and GET /api/apps/app-authentication-config/<slug>
loaded one App entity per matching default-branch version row. AppsSubscriber.afterLoad
then ran gitSyncConfigsUtilService.getDetails for each App in parallel, each on its own
pooled connections while the loading query still held one. Apps with ~12+ versions
exhausted a 25-connection pool inside a single request and failed after the 5s
pg-pool connect timeout.

Neither caller reads the hydrated fields, so both now opt out via
skipAppEditingVersionHydration, and retrieveAppDataUsingSlug fetches a single row.
The AsyncLocalStorage moves to its own file so AppsRepository can import it without
an import cycle; the subscriber re-exports it.

* chore: bump version to 3.21.91-beta

* fix: stop app afterLoad hydration taking extra DB connections

AppsSubscriber.afterLoad runs for every loaded App in parallel while the loading
query still holds its connection. It called getDetails (own transaction) and an
AppVersion lookup on fresh pooled connections, so any query loading many Apps
could exhaust the pool and fail after the 5s connect timeout.

afterLoad now passes TypeORM's LoadEvent.manager, bound to the loading
connection, to getDetails and uses it for the AppVersion lookup. getDetails
accepts an optional manager and runs its reads on it.

getAllGranularPermissions also skips the hydration, since it loads one App per
individually granted app and its callers only read app columns.

* fix: fall back to apps.name when listing owned apps on role downgrade

Apps without a non-stub version row (or with no app_name on it) were
reported by id in the "owner of apps" error. Keep apps.name ahead of the
id fallback, matching the previous behaviour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: update version to 3.21.93-beta across all components

---------

Co-authored-by: Shantanu Mane <maneshantanu.20@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

v3.21.92-beta

Toggle v3.21.92-beta's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Fix: Guard slug lookups exhausting the DB pool for apps with many ver…

…sions (#18885)

* fix: limit guard slug lookups to one app to stop pool exhaustion

findAppBySlug, findBySlug and findByAppName matched every default-branch
version row of an app and loaded one App per row, each running
AppsSubscriber.afterLoad on its own pooled connection. Apps with many
versions exhausted the pool and validate-released-app-access (and other
slug-guarded routes) timed out. LIMIT 1 keeps hydration but for one App.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: bump version to 3.21.92-beta

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

v3.21.91-beta

Toggle v3.21.91-beta's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Fix: Slug lookups exhausting the DB pool for apps with many versions (#…

…18883)

* fix: stop per-version app hydration starving the DB pool on slug lookups

GET /api/session?appId=<slug> and GET /api/apps/app-authentication-config/<slug>
loaded one App entity per matching default-branch version row. AppsSubscriber.afterLoad
then ran gitSyncConfigsUtilService.getDetails for each App in parallel, each on its own
pooled connections while the loading query still held one. Apps with ~12+ versions
exhausted a 25-connection pool inside a single request and failed after the 5s
pg-pool connect timeout.

Neither caller reads the hydrated fields, so both now opt out via
skipAppEditingVersionHydration, and retrieveAppDataUsingSlug fetches a single row.
The AsyncLocalStorage moves to its own file so AppsRepository can import it without
an import cycle; the subscriber re-exports it.

* chore: bump version to 3.21.91-beta

v3.21.90-beta

Toggle v3.21.90-beta's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Merge pull request #18829 from ToolJet/fix/tjdb-flag-allow-proxy

Fix: Keep TJDB proxy access unchanged when builder-edit flag is on

v3.20.255-lts

Toggle v3.20.255-lts's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Feature: OIDC group sync with nested claims and a delimiter (lts-3.16) (

#18799)

* feat: add delimiter column and OIDC group sync tests

Adds a nullable delimiter column to sso_config_oidc_group_sync and the
matching entity field, used by the nested-claim and delimiter handling
in the EE OIDC service.

Adds unit tests for dot-path claims, delimiters and the groups scope
rule, plus an e2e login flow driven by a small mock OIDC IdP.

* chore: update submodule pointers

* chore: move OIDC group sync tests to the EE test tree

The tests exercise EE code, so they now live under server/ee/test. The
e2e config adds that tree as a root when the submodule is present, so
community clones without it still run unchanged.

* chore: update submodule pointers

* chore: bump version to 3.2
6C0B
0.255-lts

---------

Co-authored-by: gsmithun4 <gsmithun4@gmail.com>

v3.20.254-lts

Toggle v3.20.254-lts's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Merge pull request #18854 from ToolJet/chore/ai-builder-release-6

AI Builder release 6: MCP workspace selection and authentication
0