---
id: "GHSA-v5ch-g375-82r6"
page: "https://infrastack.ai/live/GHSA-v5ch-g375-82r6"
kind: "vulnerability"
aliases: ["GHSA-v5ch-g375-82r6"]
title: "Temporary signed URL expiration bypass"
severity: "medium"
cvss: 4.8
epss: null
exploited: false
status: "open"
category: "package"
products: [{"name": "laravel/framework", "fixed": ["12.72.0"], "affected": "< 12.72.0", "ecosystem": "composer"}, {"name": "laravel/framework", "fixed": ["13.41.0"], "affected": ">= 13.0.0, < 13.41.0", "ecosystem": "composer"}]
ecosystems: ["composer"]
tags: ["laravel", "package", "php", "signed-urls"]
not_affected_if: ["no-signed-urls", "short-url-limit"]
published_at: "2026-11-11T13:52:08+00:00"
first_seen_at: "2026-11-11T14:01:45+00:00"
updated_at: "2026-11-11T14:02:12+00:00"
sources: [{"source": "ghsa-repo", "url": "https://github.com/laravel/framework/security/advisories/GHSA-v5ch-g375-82r6", "first_seen_at": "2026-11-11T14:01:45+00:00"}]
exploit_sources: []
---

# Temporary signed URL expiration bypass

Link for people: https://infrastack.ai/live/GHSA-v5ch-g375-82r6 (this .md is for agents)

When a long request exceeds PHP's max_input_vars limit, the expires parameter can be dropped from the parsed query while the signature is still checked against the raw query string. An attacker can then reuse an expired temporary signed URL and have it accepted.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- composer:laravel/framework affected < 12.72.0 fixed 12.72.0
- composer:laravel/framework affected >= 13.0.0, < 13.41.0 fixed 13.41.0

## How to check

- Check the Laravel version in `composer.lock` for `laravel/framework`.
- Check the PHP `max_input_vars` setting with `php -i | grep max_input_vars`.
- Check whether the app uses the `signed` middleware on routes that rely on expiring URLs.

## Fix

- `laravel/framework` `12.72.0` for the 12.x line
- `laravel/framework` `13.41.0` for the 13.x line

## Timeline

- 2026-11-11T14:01:45+00:00 ghsa-repo https://github.com/laravel/framework/security/advisories/GHSA-v5ch-g375-82r6

## Documents

- [advisory] Maintainer's advisory: github.com https://github.com/laravel/framework/security/advisories/GHSA-v5ch-g375-82r6

## From the sources

### Impact

When PHP's `max_input_vars` limit causes the `expires` query parameter to be dropped from the parsed query, Laravel's signed URL validation can still verify the signature against the raw query string. `signatureHasNotExpired()` then treats the URL as non-expiring, so an expired temporary signed URL may be accepted. Exploitation requires a request line long enough to exceed `max_input_vars`, which depends on server and proxy limits.

### Patches

This issue has been patched in Laravel 12.72.0 and 13.41.0: https://github.com/laravel/framework/pull/62349. Users should upgrade to one of these versions or later.

### Workarounds

- Limit URL length at the web server. Default nginx and Apache settings already reject the long URL the attack needs.
- If web server configuration is unavailable, add a middleware ahead of `signed` that returns an error when the raw query has more pairs than `max_input_vars` or when `expires` appears in the raw query but is missing from the parsed one.

---

_Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai_
