VYPR
Moderate severityNVD Advisory· Published Oct 19, 2021· Updated Aug 3, 2024

Open Redirect in firefly-iii/firefly-iii

CVE-2021-3851

Description

firefly-iii is vulnerable to URL Redirection to Untrusted Site

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
grumpydictator/firefly-iiiPackagist
< 5.6.25.6.2

Affected products

1

Patches

1
8662dfa4c0f7

Fix unsecure redirect code.

https://github.com/firefly-iii/firefly-iiiJames ColeOct 2, 2021via ghsa
3 files changed · +58 2
  • app/Exceptions/Handler.php+57 0 modified
    @@ -29,8 +29,11 @@
     use ErrorException;
     use FireflyIII\Jobs\MailError;
     use Illuminate\Auth\AuthenticationException;
    +use Illuminate\Contracts\Foundation\Application;
     use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
    +use Illuminate\Http\RedirectResponse;
     use Illuminate\Http\Request;
    +use Illuminate\Routing\Redirector;
     use Illuminate\Session\TokenMismatchException;
     use Illuminate\Support\Arr;
     use Illuminate\Validation\ValidationException as LaravelValidationException;
    @@ -187,4 +190,58 @@ private function shouldntReportLocal(Throwable $e): bool
                 )
             );
         }
    +
    +    /**
    +     * Convert a validation exception into a response.
    +     *
    +     * @param Request                    $request
    +     * @param LaravelValidationException $exception
    +     *
    +     * @return Application|RedirectResponse|Redirector
    +     */
    +    protected function invalid($request, LaravelValidationException $exception): Application|RedirectResponse|Redirector
    +    {
    +        // protect against open redirect when submitting invalid forms.
    +        $previous = $this->getPreviousUrl();
    +        $redirect = $this->getRedirectUrl($exception);
    +
    +        return redirect($redirect ?? $previous)
    +            ->withInput(Arr::except($request->input(), $this->dontFlash))
    +            ->withErrors($exception->errors(), $request->input('_error_bag', $exception->errorBag));
    +    }
    +
    +    /**
    +     * Only return the previousUrl() if it is a valid URL. Return default redirect otherwise.
    +     *
    +     * @return string
    +     */
    +    private function getPreviousUrl(): string
    +    {
    +        $safe         = route('index');
    +        $previous     = url()->previous();
    +        $previousHost = parse_url($previous, PHP_URL_HOST);
    +        $safeHost     = parse_url($safe, PHP_URL_HOST);
    +
    +        return null !== $previousHost && $previousHost === $safeHost ? $previous : $safe;
    +    }
    +
    +    /**
    +     * Only return the redirectTo property from the exception if it is a valid URL. Return NULL otherwise.
    +     *
    +     * @param LaravelValidationException $exception
    +     *
    +     * @return string|null
    +     */
    +    private function getRedirectUrl(LaravelValidationException $exception): ?string
    +    {
    +        if (null === $exception->redirectTo) {
    +            return null;
    +        }
    +        $safe         = route('index');
    +        $previous     = $exception->redirectTo;
    +        $previousHost = parse_url($previous, PHP_URL_HOST);
    +        $safeHost     = parse_url($safe, PHP_URL_HOST);
    +
    +        return null !== $previousHost && $previousHost === $safeHost ? $previous : $safe;
    +    }
     }
    
  • app/Http/Middleware/StartFireflySession.php+0 1 modified
    @@ -45,7 +45,6 @@ protected function storeCurrentUrl(Request $request, $session): void
             $url          = $request->fullUrl();
             $forbiddenWords = strpos($url, 'offline') || strpos($url, 'jscript') || strpos($url, 'delete') || strpos($url, '/login') || strpos($url, '/json') || strpos($url, 'serviceworker') || strpos($url, '/attachments/view');
     
    -        // also stop remembering "delete" URL's.
             if (false === $forbiddenWords
                 && 'GET' === $request->method()
                 && !$request->ajax()) {
    
  • app/Support/Http/Controllers/UserNavigation.php+1 1 modified
    @@ -183,7 +183,7 @@ final protected function rememberPreviousUri(string $identifier): ?string
             // get host of previous URL:
             $previous = parse_url($return, PHP_URL_HOST);
     
    -        if ($default === $previous && (null === $errors || (0 === $errors->count())) && !Str::contains($return, $forbidden)) {
    +        if (null !== $previous && $default === $previous && (null === $errors || (0 === $errors->count())) && !Str::contains($return, $forbidden)) {
                 Log::debug(sprintf('Saving URL %s under key %s', $return, $identifier));
                 session()->put($identifier, $return);
     
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.