Vulnerability: invoiceninja is vulnerable to Cross-site Scripting invoiceninja is vulnerable to Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
Vulnerability ID: GHSA-xg6r-5gx4-qxjm
CWE: CWE-79
Severity score: 5.4
Project: https://github.com/invoiceninja/invoiceninja
Published: 2022-01-06
File: app/Http/Controllers/Auth/ContactForgotPasswordController.php
Commit message: Fixes for client password reset
Commit author: David Bomba

Vulnerable version (before fix):
 public function broker()      public function sendResetLinkEmail(ContactPasswordResetRequest $request)     {          if(Ninja::isHosted() && $request->session()->has('company_key'))             MultiDB::findAndSetDbByCompanyKey($request->session()->get('company_key'));                  $this->validateEmail($request);          $company = Company::where('company_key', $request->session()->get('company_key'))->first();         $contact = ClientContact::where(['company_id' => $company->id, 'email' => $request->input('email')])->first();          $response = false;  public function sendResetLinkEmail(ContactPasswordResetRequest $request)             return $this->sendResetLinkFailedResponse($request, Password::INVALID_USER);          // We will send the password reset link to this user. Once we have attempted         // to send the link, we will examine the response then see the message we         // need to show to the user. Finally, we'll send out a proper response.         // $response = $this->broker()->sendResetLink(         //     $this->credentials($request)

Fixed version (after fix):
 public function broker()      public function sendResetLinkEmail(ContactPasswordResetRequest $request)     {         if(Ninja::isHosted() && $request->has('company_key'))             MultiDB::findAndSetDbByCompanyKey($request->input('company_key'));                  $this->validateEmail($request);          // $company = Company::where('company_key', $request->input('company_key'))->first();         // $contact = ClientContact::where(['company_id' => $company->id, 'email' => $request->input('email')])->first();          $contact = ClientContact::where(['email' => $request->input('email')])->first();          $response = false;  public function sendResetLinkEmail(ContactPasswordResetRequest $request)             return $this->sendResetLinkFailedResponse($request, Password::INVALID_USER);          // We will send the password reset link to this user. Once we have attempted         // to send the link, we will examine thuser@example.ce response then see the message we         // need to show to the user. Finally, we'll send out a proper response.         // $response = $this->broker()->sendResetLink(         //     $this->credentials($request)

Patch:
patch: @@ -93,14 +93,15 @@ public function broker()
 
     public function sendResetLinkEmail(ContactPasswordResetRequest $request)
     {
-
-        if(Ninja::isHosted() && $request->session()->has('company_key'))
-            MultiDB::findAndSetDbByCompanyKey($request->session()->get('company_key'));
+        if(Ninja::isHosted() && $request->has('company_key'))
+            MultiDB::findAndSetDbByCompanyKey($request->input('company_key'));
         
         $this->validateEmail($request);
 
-        $company = Company::where('company_key', $request->session()->get('company_key'))->first();
-        $contact = ClientContact::where(['company_id' => $company->id, 'email' => $request->input('email')])->first();
+        // $company = Company::where('company_key', $request->input('company_key'))->first();
+        // $contact = ClientContact::where(['company_id' => $company->id, 'email' => $request->input('email')])->first();
+
+        $contact = ClientContact::where(['email' => $request->input('email')])->first();
 
         $response = false;
 
@@ -117,7 +118,7 @@ public function sendResetLinkEmail(ContactPasswordResetRequest $request)
             return $this->sendResetLinkFailedResponse($request, Password::INVALID_USER);
 
         // We will send the password reset link to this user. Once we have attempted
-        // to send the link, we will examine the response then see the message we
+        // to send the link, we will examine thuser@example.ce response then see the message we
         // need to show to the user. Finally, we'll send out a proper response.
         // $response = $this->broker()->sendResetLink(
         //     $this->credentials($request)
path: app/Http/Controllers/Auth/ContactForgotPasswordController.php