CVE-2026-58654
MediumCVSS 4.3Exploitation Probability (EPSS)
Low risk17th percentile - higher than 17% of all known CVEs
Summary
The Grav API plugin (getgrav/grav-plugin-api) version 1.0.0 contains an unrestricted file upload vulnerability in the avatar upload endpoint (/api/v1/users/user/avatar). The endpoint validates only the client-declared MIME type (getClientMediaType) beginning with 'image/' and does not inspect the actual file content or restrict the resulting extension, allowing an authenticated user to store arbitrary content — including PHP code, SVG with embedded JavaScript, and polyglot payloads — under user/accounts/avatars/ with predictable filenames. Direct HTTP access to the stored files is blocked by .htaccess (returns 403), but the files persist on disk and could lead to remote code execution or stored XSS in the presence of a path traversal flaw or server misconfiguration. Fixed in 1.0.1.
Risk Assessment
The risk for the organization includes potential remote code execution (RCE) or stored XSS if the server is misconfigured or another path traversal vulnerability exists. Even without direct HTTP access, files remain on disk and could be exploited in combination with other flaws.
Recommendation
It is recommended to immediately update the Grav API plugin to version 1.0.1 or later. Additionally, review server configuration to block access to the user/accounts/avatars/ directory and consider adding server-side file content validation.
Other vulnerabilities in Grav API plugin
See all- CVE-2026-62668Critical
Vulnerability in Grav API Plugin (plugin for Grav CMS) before version 1.0.6. WebhookController.php accepts webhook URLs after only FILTER_VALIDATE_URL syntax validation, and WebhookDispatcher.php initializes cURL without CURLOPT_PROTOCOLS or CURLOPT_REDIR_PROTOCOLS restrictions. An account with api.webhooks.write can submit file, dict, gopher, private-network, or link-local targets, retrieve local files and delivery response bodies, and pivot requests to internal services or cloud metadata endpoints. Fixed in version 1.0.6.
- CVE-2026-65007Critical
The Grav api plugin (grav-plugin-api) before version 1.0.8 fails to properly authorize API key generation and revocation. It intercepts the apiKeyGenerate/apiKeyRevoke admin tasks before the account-management ACL runs and authorizes the caller on only the admin.login permission (the baseline permission held by every panel user). This allows any user with admin.login to mint a persistent API key bound to any account, and the forged key inherits the target account's API permissions. On installs where an API-enabled account holds broader permissions, this enables account impersonation and privilege escalation up to account takeover.
- CVE-2026-61451Critical
The Grav API plugin (grav-plugin-api) before version 1.0.4 does not validate the origin of the admin_base_url field in the POST /api/v1/auth/forgot-password endpoint. The sanitizeHttpUrl() function only checks the URL scheme (http/https) and never verifies the host against the server's own origin, allowing an attacker to supply an arbitrary host. An unauthenticated attacker can cause the password reset email sent to a victim to contain a reset link pointing at an attacker-controlled server; when the victim follows the link, the valid reset token is disclosed to the attacker, enabling full account takeover.
- CVE-2026-86196High
Grav API plugin versions before 1.0.20 build password reset links from the untrusted Host header in the forgot-password endpoint, allowing unauthenticated attackers to redirect reset tokens to attacker-controlled domains. Attackers can send password reset requests for any account with a malicious Host header, intercept the reset token from victim emails, and complete account takeover including super-admin accounts.
- CVE-2026-80204Medium
The Grav API plugin before 1.0.18 does not enforce API-key scope caps in the injectSecurityTab() function of BlueprintController. A caller with a scoped API key may see and potentially edit page permission fields beyond the granted scope.
- CVE-2026-56708Medium
Grav API plugin before 1.0.16 contains a server-side request forgery vulnerability in webhook delivery that allows attackers to bypass hostname validation by DNS rebinding. Attackers controlling authoritative DNS for a configured webhook hostname can answer validation lookups with public addresses and delivery lookups with private addresses to reach internal network resources.
- CVE-2026-64852High
Grav API Plugin prior to 1.0.8 intercepts the apiKeyGenerate and apiKeyRevoke admin tasks in user/plugins/api/api.php and authorizes the caller with only admin.login. A basic panel user can select another account from the route, create a persistent ApiKeyManager credential bound to that target, and inherit the target's API permissions, including api.super or administrative write access when present. This issue is fixed in version 1.0.8.
- CVE-2026-63408High
Grav API Plugin prior to 1.0.0-rc.16 accepts a JWT from the token URL query parameter on every /api/v1 route, including state-changing endpoints. Request URLs consequently expose valid access tokens through Apache, proxy, and CDN logs, browser history, and Referer headers, allowing a party with access to those records to reuse the token with the owner's API privileges. This issue is fixed in version 1.0.0-rc.16.
- CVE-2026-63407High
Grav API Plugin prior to 1.0.0-rc.16 in CorsMiddleware returns Access-Control-Allow-Origin: * and permissive OPTIONS responses for authenticated /api/v1 endpoints. JavaScript from any origin can submit an attacker-obtained JWT through the Authorization or X-API-Token header, read the authenticated response, and perform write operations with the token owner's privileges, enabling data exfiltration and account modification. This issue is fixed in version 1.0.0-rc.16.
- CVE-2026-62667High
The Grav API plugin before version 1.0.6 contains a vulnerability where ApiKeyManager::generateKey() stores a declared scopes array, but ApiKeyAuthenticator::authenticate() does not read keyData[scopes] and returns the owning user's complete identity. Consequently, AbstractApiController::requirePermission() evaluates the full user ACL, so a key issued for a read-only scope can perform every write, delete, and administrative operation available to the owner. This issue is fixed in version 1.0.6.
Original NVD description (English source)
The Grav API plugin (getgrav/grav-plugin-api) 1.0.0 contains an unrestricted file upload vulnerability in the avatar upload endpoint (/api/v1/users/user/avatar). The endpoint validates only the client-declared MIME type (getClientMediaType) beginning with 'image/' and does not inspect the actual file content or restrict the resulting extension, allowing an authenticated user to store arbitrary content — including PHP code, SVG with embedded JavaScript, and polyglot payloads — under user/accounts/avatars/ with predictable filenames. Direct HTTP access to the stored files is blocked by .htaccess (returns 403), but the files persist on disk and could lead to remote code execution or stored XSS in the presence of a path traversal flaw or server misconfiguration. Fixed in 1.0.1.
Vulnerability data from NVD (NIST) · CISA KEV · EPSS

