Authentication bypass in Octobercms
Description
octobercms in a CMS platform based on the Laravel PHP Framework. In affected versions of the october/system package an attacker can exploit this vulnerability to bypass authentication and takeover of and user account on an October CMS server. The vulnerability is exploitable by unauthenticated users via a specially crafted request. This only affects frontend users and the attacker must obtain a Laravel secret key for cookie encryption and signing in order to exploit this vulnerability. The issue has been patched in Build 472 and v1.1.5.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
october/systemPackagist | < 1.0.472 | 1.0.472 |
october/systemPackagist | >= 1.1.1, < 1.1.5 | 1.1.5 |
Affected products
1- Range: >= 1.0.471, < 1.0.472
Patches
22 files changed · +8 −8
src/Auth/Models/Role.php+4 −4 modified@@ -84,7 +84,7 @@ public function hasAccess($permissions, $all = true) // We will make sure that the merged permission does not // exactly match our permission, but starts with it. - if ($checkPermission != $rolePermission && starts_with($rolePermission, $checkPermission) && $value === 1) { + if ($checkPermission != $rolePermission && starts_with($rolePermission, $checkPermission) && (int) $value === 1) { $matched = true; break; } @@ -102,7 +102,7 @@ public function hasAccess($permissions, $all = true) // We will make sure that the merged permission does not // exactly match our permission, but ends with it. - if ($checkPermission != $rolePermission && ends_with($rolePermission, $checkPermission) && $value === 1) { + if ($checkPermission != $rolePermission && ends_with($rolePermission, $checkPermission) && (int) $value === 1) { $matched = true; break; } @@ -121,14 +121,14 @@ public function hasAccess($permissions, $all = true) // We will make sure that the merged permission does not // exactly match our permission, but starts with it. - if ($checkGroupPermission != $permission && starts_with($permission, $checkGroupPermission) && $value === 1) { + if ($checkGroupPermission != $permission && starts_with($permission, $checkGroupPermission) && (int) $value === 1) { $matched = true; break; } } // Otherwise, we'll fallback to standard permissions checking where // we match that permissions explicitly exist. - elseif ($permission === $rolePermission && $rolePermissions[$permission] === 1) { + elseif ($permission === $rolePermission && (int) $rolePermissions[$permission] === 1) { $matched = true; break; }
src/Auth/Models/User.php+4 −4 modified@@ -481,7 +481,7 @@ public function hasPermission($permissions, $all = true) // We will make sure that the merged permission does not // exactly match our permission, but starts with it. - if ($checkPermission != $mergedPermission && starts_with($mergedPermission, $checkPermission) && $value === 1) { + if ($checkPermission != $mergedPermission && starts_with($mergedPermission, $checkPermission) && (int) $value === 1) { $matched = true; break; } @@ -496,7 +496,7 @@ public function hasPermission($permissions, $all = true) // We will make sure that the merged permission does not // exactly match our permission, but ends with it. - if ($checkPermission != $mergedPermission && ends_with($mergedPermission, $checkPermission) && $value === 1) { + if ($checkPermission != $mergedPermission && ends_with($mergedPermission, $checkPermission) && (int) $value === 1) { $matched = true; break; } @@ -515,15 +515,15 @@ public function hasPermission($permissions, $all = true) // We will make sure that the merged permission does not // exactly match our permission, but starts with it. - if ($checkMergedPermission != $permission && starts_with($permission, $checkMergedPermission) && $value === 1) { + if ($checkMergedPermission != $permission && starts_with($permission, $checkMergedPermission) && (int) $value === 1) { $matched = true; break; } } // Otherwise, we'll fallback to standard permissions checking where // we match that permissions explicitly exist. - elseif ($permission === $mergedPermission && $mergedPermissions[$permission] === 1) { + elseif ($permission === $mergedPermission && (int) $mergedPermissions[$permission] === 1) { $matched = true; break; }
016a297b1becBackport code audit from 1.2
4 files changed · +13 −13
src/Auth/Manager.php+1 −1 modified@@ -241,7 +241,7 @@ public function findUserByCredentials(array $credentials) foreach ($hashedCredentials as $credential => $value) { if (!$user->checkHashValue($credential, $value)) { // Incorrect password - if ($credential == 'password') { + if ($credential === 'password') { throw new AuthException(sprintf( 'A user was found to match all plain text credentials however hashed credential "%s" did not match.', $credential
src/Auth/Models/Role.php+4 −4 modified@@ -84,7 +84,7 @@ public function hasAccess($permissions, $all = true) // We will make sure that the merged permission does not // exactly match our permission, but starts with it. - if ($checkPermission != $rolePermission && starts_with($rolePermission, $checkPermission) && $value == 1) { + if ($checkPermission != $rolePermission && starts_with($rolePermission, $checkPermission) && $value === 1) { $matched = true; break; } @@ -102,7 +102,7 @@ public function hasAccess($permissions, $all = true) // We will make sure that the merged permission does not // exactly match our permission, but ends with it. - if ($checkPermission != $rolePermission && ends_with($rolePermission, $checkPermission) && $value == 1) { + if ($checkPermission != $rolePermission && ends_with($rolePermission, $checkPermission) && $value === 1) { $matched = true; break; } @@ -121,14 +121,14 @@ public function hasAccess($permissions, $all = true) // We will make sure that the merged permission does not // exactly match our permission, but starts with it. - if ($checkGroupPermission != $permission && starts_with($permission, $checkGroupPermission) && $value == 1) { + if ($checkGroupPermission != $permission && starts_with($permission, $checkGroupPermission) && $value === 1) { $matched = true; break; } } // Otherwise, we'll fallback to standard permissions checking where // we match that permissions explicitly exist. - elseif ($permission == $rolePermission && $rolePermissions[$permission] == 1) { + elseif ($permission === $rolePermission && $rolePermissions[$permission] === 1) { $matched = true; break; }
src/Auth/Models/Throttle.php+1 −1 modified@@ -99,7 +99,7 @@ public function clearLoginAttempts() // anything either as clearing login attempts // makes us unsuspended. We need to manually // call unsuspend() in order to unsuspend. - if ($this->getLoginAttempts() == 0 or $this->is_suspended) { + if ($this->getLoginAttempts() === 0 or $this->is_suspended) { return; }
src/Auth/Models/User.php+7 −7 modified@@ -190,7 +190,7 @@ public function checkPersistCode($persistCode) return false; } - return $persistCode == $this->persist_code; + return $persistCode === $this->persist_code; } // @@ -278,7 +278,7 @@ public function checkResetPasswordCode($resetCode) return false; } - return ($this->reset_password_code == $resetCode); + return ($this->reset_password_code === $resetCode); } /** @@ -386,7 +386,7 @@ public function removeGroup($group) public function inGroup($group) { foreach ($this->getGroups() as $_group) { - if ($_group->getKey() == $group->getKey()) { + if ($_group->getKey() === $group->getKey()) { return true; } } @@ -481,7 +481,7 @@ public function hasPermission($permissions, $all = true) // We will make sure that the merged permission does not // exactly match our permission, but starts with it. - if ($checkPermission != $mergedPermission && starts_with($mergedPermission, $checkPermission) && $value == 1) { + if ($checkPermission != $mergedPermission && starts_with($mergedPermission, $checkPermission) && $value === 1) { $matched = true; break; } @@ -496,7 +496,7 @@ public function hasPermission($permissions, $all = true) // We will make sure that the merged permission does not // exactly match our permission, but ends with it. - if ($checkPermission != $mergedPermission && ends_with($mergedPermission, $checkPermission) && $value == 1) { + if ($checkPermission != $mergedPermission && ends_with($mergedPermission, $checkPermission) && $value === 1) { $matched = true; break; } @@ -515,15 +515,15 @@ public function hasPermission($permissions, $all = true) // We will make sure that the merged permission does not // exactly match our permission, but starts with it. - if ($checkMergedPermission != $permission && starts_with($permission, $checkMergedPermission) && $value == 1) { + if ($checkMergedPermission != $permission && starts_with($permission, $checkMergedPermission) && $value === 1) { $matched = true; break; } } // Otherwise, we'll fallback to standard permissions checking where // we match that permissions explicitly exist. - elseif ($permission == $mergedPermission && $mergedPermissions[$permission] == 1) { + elseif ($permission === $mergedPermission && $mergedPermissions[$permission] === 1) { $matched = true; break; }
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
5- github.com/advisories/GHSA-h76r-vgf3-j6w5ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2021-29487ghsaADVISORY
- github.com/octobercms/library/commit/016a297b1bec55d2e53bc889458ed2cb5c3e9374ghsax_refsource_MISCWEB
- github.com/octobercms/library/commit/5bd1a28140b825baebe6becd4f7562299d3de3b9ghsax_refsource_MISCWEB
- github.com/octobercms/october/security/advisories/GHSA-h76r-vgf3-j6w5ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.