VYPR
Moderate severityNVD Advisory· Published Nov 13, 2021· Updated Aug 3, 2024

Cross-Site Request Forgery (CSRF) in area17/twill

CVE-2021-3932

Description

twill is vulnerable to Cross-Site Request Forgery (CSRF)

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
area17/twillPackagist
< 1.2.51.2.5
area17/twillPackagist
>= 2.0.0, < 2.5.32.5.3

Affected products

1

Patches

2
81d80d1fbbdd

Use POST action for logout links

https://github.com/area17/twillPatrick BoivinNov 5, 2021via ghsa
6 files changed · +26 3
  • frontend/js/behaviors/logoutButton.js+16 0 added
    @@ -0,0 +1,16 @@
    +// POST logout action
    +
    +const logoutButton = function () {
    +  const logoutForm = document.querySelector('[data-logout-form]')
    +
    +  if (!logoutForm) return
    +
    +  document.body.addEventListener('click', e => {
    +    if (e.target.hasAttribute('data-logout-btn')) {
    +      e.preventDefault()
    +      logoutForm.submit()
    +    }
    +  })
    +}
    +
    +export default logoutButton
    
  • frontend/js/main.js+2 0 modified
    @@ -4,12 +4,14 @@ import 'styles/app.scss'
     import Vue from 'vue'
     import navToggle from '@/behaviors/navToggle'
     import showEnvLine from '@/behaviors/showEnvLine'
    +import logoutButton from '@/behaviors/logoutButton'
     import search from '@/main-search'
     import merge from 'lodash/merge'
     
     const A17Init = function () {
       navToggle()
       showEnvLine()
    +  logoutButton()
     }
     
     // User header dropdown
    
  • routes/auth.php+1 1 modified
    @@ -5,7 +5,7 @@
     if (config('twill.enabled.users-management')) {
         Route::get('login', 'LoginController@showLoginForm')->name('login.form');
         Route::post('login', 'LoginController@login')->name('login');
    -    Route::get('logout', 'LoginController@logout')->name('logout');
    +    Route::post('logout', 'LoginController@logout')->name('logout');
     
         Route::get('password/reset', 'ForgotPasswordController@showLinkRequestForm')->name('password.reset.link');
         Route::post('password/email', 'ForgotPasswordController@sendResetLinkEmail')->name('password.reset.email');
    
  • views/layouts/main.blade.php+5 0 modified
    @@ -71,6 +71,11 @@
                     @include('twill::partials.footer')
                 </section>
             </div>
    +
    +        <form class="visually-hidden" method="POST" action="{{ route('admin.logout') }}" data-logout-form>
    +            @csrf
    +        </form>
    +
             <script>
                 window['{{ config('twill.js_namespace') }}'] = {};
                 window['{{ config('twill.js_namespace') }}'].version = '{{ config('twill.version') }}';
    
  • views/partials/navigation/_overlay_navigation.blade.php+1 1 modified
    @@ -22,7 +22,7 @@
                         @if(isset($currentUser))
                             <a href="{{ route('admin.users.index') }}">{{ twillTrans('twill::lang.nav.cms-users') }}</a><br />
                             <a href="{{ route('admin.users.edit', $currentUser->id) }}">{{ twillTrans('twill::lang.nav.settings') }}</a><br />
    -                        <a href="{{ route('admin.logout') }}">{{ twillTrans('twill::lang.nav.logout') }}</a>
    +                        <a href="#" data-logout-btn>{{ twillTrans('twill::lang.nav.logout') }}</a>
                         @endif
                     </div>
                 </div>
    
  • views/partials/navigation/_user.blade.php+1 1 modified
    @@ -14,7 +14,7 @@
                     <a href="{{ route('admin.users.index') }}">{{ twillTrans('twill::lang.nav.cms-users') }}</a>
                 @endcan
                 <a href="{{ route('admin.users.edit', $currentUser->id) }}">{{ twillTrans('twill::lang.nav.settings') }}</a>
    -            <a href="{{ route('admin.logout') }}">{{ twillTrans('twill::lang.nav.logout') }}</a>
    +            <a href="#" data-logout-btn>{{ twillTrans('twill::lang.nav.logout') }}</a>
             </div>
         </a17-dropdown>
     @endif
    
5cded9fc

Use POST action for logout links

https://github.com/area17/twillPatrick BoivinNov 5, 2021via ghsa
6 files changed · +26 3
  • frontend/js/behaviors/logoutButton.js+16 0 added
    @@ -0,0 +1,16 @@
    +// POST logout action
    +
    +const logoutButton = function () {
    +  const logoutForm = document.querySelector('[data-logout-form]')
    +
    +  if (!logoutForm) return
    +
    +  document.body.addEventListener('click', e => {
    +    if (e.target.hasAttribute('data-logout-btn')) {
    +      e.preventDefault()
    +      logoutForm.submit()
    +    }
    +  })
    +}
    +
    +export default logoutButton
    
  • frontend/js/main.js+2 0 modified
    @@ -4,12 +4,14 @@ import 'styles/app.scss'
     import Vue from 'vue'
     import navToggle from '@/behaviors/navToggle'
     import showEnvLine from '@/behaviors/showEnvLine'
    +import logoutButton from '@/behaviors/logoutButton'
     import search from '@/main-search'
     import merge from 'lodash/merge'
     
     const A17Init = function () {
       navToggle()
       showEnvLine()
    +  logoutButton()
     }
     
     // User header dropdown
    
  • routes/auth.php+1 1 modified
    @@ -5,7 +5,7 @@
     if (config('twill.enabled.users-management')) {
         Route::get('login', 'LoginController@showLoginForm')->name('login.form');
         Route::post('login', 'LoginController@login')->name('login');
    -    Route::get('logout', 'LoginController@logout')->name('logout');
    +    Route::post('logout', 'LoginController@logout')->name('logout');
     
         Route::get('password/reset', 'ForgotPasswordController@showLinkRequestForm')->name('password.reset.link');
         Route::post('password/email', 'ForgotPasswordController@sendResetLinkEmail')->name('password.reset.email');
    
  • views/layouts/main.blade.php+5 0 modified
    @@ -71,6 +71,11 @@
                     @include('twill::partials.footer')
                 </section>
             </div>
    +
    +        <form class="visually-hidden" method="POST" action="{{ route('admin.logout') }}" data-logout-form>
    +            @csrf
    +        </form>
    +
             <script>
                 window['{{ config('twill.js_namespace') }}'] = {};
                 window['{{ config('twill.js_namespace') }}'].version = '{{ config('twill.version') }}';
    
  • views/partials/navigation/_overlay_navigation.blade.php+1 1 modified
    @@ -22,7 +22,7 @@
                         @if(isset($currentUser))
                             <a href="{{ route('admin.users.index') }}">{{ twillTrans('twill::lang.nav.cms-users') }}</a><br />
                             <a href="{{ route('admin.users.edit', $currentUser->id) }}">{{ twillTrans('twill::lang.nav.settings') }}</a><br />
    -                        <a href="{{ route('admin.logout') }}">{{ twillTrans('twill::lang.nav.logout') }}</a>
    +                        <a href="#" data-logout-btn>{{ twillTrans('twill::lang.nav.logout') }}</a>
                         @endif
                     </div>
                 </div>
    
  • views/partials/navigation/_user.blade.php+1 1 modified
    @@ -14,7 +14,7 @@
                     <a href="{{ route('admin.users.index') }}">{{ twillTrans('twill::lang.nav.cms-users') }}</a>
                 @endcan
                 <a href="{{ route('admin.users.edit', $currentUser->id) }}">{{ twillTrans('twill::lang.nav.settings') }}</a>
    -            <a href="{{ route('admin.logout') }}">{{ twillTrans('twill::lang.nav.logout') }}</a>
    +            <a href="#" data-logout-btn>{{ twillTrans('twill::lang.nav.logout') }}</a>
             </div>
         </a17-dropdown>
     @endif
    

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

8

News mentions

0

No linked articles in our index yet.