CVE-2022-23067 (published 2022-05-18T14:15Z)

ToolJet versions v0.5.0 to v1.2.2 are vulnerable to token leakage via Referer header that leads to account takeover . If the user opens the invite link/signup link and then clicks on any external links within the page, it leaks the password set token/signup token in the referer header. Using these tokens the attacker can access the user’s account.

Severity: MEDIUM
CVSS v2 base score: 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 8.8, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/ToolJet/ToolJet
commit_details: repo_url: https://github.com/ToolJet/ToolJet
author: Akshay
author_date: 2022-03-03 20:16:35+05:30
msg: Fix token present in referrer header (#2413)
repository: repo_url: https://github.com/ToolJet/ToolJet
repo_name: ToolJet/ToolJet
description: Low-code platform for building business applications. Connect to databases, cloud storages, GraphQL, API endpoints, Airtable, Google sheets, OpenAI, etc and build apps using drag and drop application builder. Built using JavaScript/TypeScript. 🚀
repo_language: JavaScript
owner: ToolJet
file_changes: filename: App.jsx
change_type: ModificationType.MODIFY
diff: @@ -1,12 +1,12 @@
 import React from 'react';
-import { Router, Route } from 'react-router-dom';
+import { Router, Route, Redirect } from 'react-router-dom';
 import { history } from '@/_helpers';
 import { authenticationService, tooljetService } from '@/_services';
 import { PrivateRoute } from '@/_components';
 import { HomePage } from '@/HomePage';
 import { LoginPage } from '@/LoginPage';
 import { SignupPage } from '@/SignupPage';
-import { InvitationPage } from '@/InvitationPage';
+import { ConfirmationPage } from '@/ConfirmationPage';
 import { Authorize } from '@/Oauth2';
 import { Authorize as Oauth } from '@/Oauth';
 import { Editor, Viewer } from '@/Editor';
@@ -118,7 +118,18 @@ class App extends React.Component {
             <Route path="/signup" component={SignupPage} />
             <Route path="/forgot-password" component={ForgotPassword} />
             <Route path="/reset-password" component={ResetPassword} />
-            <Route path="/invitations/:token" component={InvitationPage} />
+            <Route
+              path="/invitations/:token"
+              render={(props) => (
+                <Redirect
+                  to={{
+                    pathname: '/confirm',
+                    state: { token: props.match.params.token, search: props.location.search },
+                  }}
+                />
+              )}
+            />
+            <Route path="/confirm" component={ConfirmationPage} />
             <PrivateRoute
               exact
               path="/apps/:id"

programming_language: TypeScript
filename: ConfirmationPage.jsx
change_type: ModificationType.RENAME
diff: @@ -3,13 +3,13 @@ import { userService } from '@/_services';
 import { toast } from 'react-hot-toast';
 import queryString from 'query-string';
 
-class InvitationPage extends React.Component {
+class ConfirmationPage extends React.Component {
   constructor(props) {
     super(props);
 
     this.state = {
       isLoading: false,
-      newSignup: queryString.parse(props.location.search).signup,
+      newSignup: queryString.parse(props.location.state.search).signup,
     };
     this.formRef = React.createRef(null);
   }
@@ -26,7 +26,7 @@ class InvitationPage extends React.Component {
   setPassword = (e) => {
     e.preventDefault();
 
-    const token = this.props.match.params.token;
+    const token = this.props.location.state.token;
     const { password, organization, role, newSignup, firstName, lastName, password_confirmation } = this.state;
     this.setState({ isLoading: true });
 
@@ -203,4 +203,4 @@ class InvitationPage extends React.Component {
   }
 }
 
-export { InvitationPage };
+export { ConfirmationPage };

programming_language: TypeScript
filename: index.js
change_type: ModificationType.ADD
diff: @@ -0,0 +1 @@
+export * from './ConfirmationPage';

programming_language: TypeScript
filename: index.js
change_type: ModificationType.DELETE
diff: @@ -1 +0,0 @@
-export * from './InvitationPage';

programming_language: unknown