open-telemetry / open-telemetry/opentelemetry-php
Laravel instrumentation: url.full is recorded unredacted, leaking signed-URL signatures
@ChrisLightfootWild is already working on this.
Since Aug 12, 2026.
- Dominant language
- PHP
- Stars
- 912
- Forks
- 232
- Avg merge
- 7d 16h
- Merged PRs (30d)
- 4
Description
What happens
opentelemetry-auto-laravel records the full request URL, including the query string, with no redaction of sensitive query parameters.
Server spans — src/Hooks/Illuminate/Contracts/Http/Kernel.php:58:
->setAttribute(TraceAttributes::URL_FULL, $request->fullUrl())
Client spans — src/Watchers/ClientRequestWatcher.php:50-55 strips userinfo, then re-appends the query string verbatim:
$parsedUrl = collect(parse_url($request->request->url()) ?: []);
$processedUrl = $parsedUrl->get('scheme', 'http') . '://' . $parsedUrl->get('host') . $parsedUrl->get('path', '');
if ($parsedUrl->has('query')) {
$processedUrl .= '?' . $parsedUrl->get('query'); // <- unredacted
}
Why this matters for Laravel specifically
Laravel's signed URLs are a core framework feature used for email verification, password-reset style flows and temporary download links. UrlGenerator::signedRoute() / temporarySignedRoute() append the HMAC as a query parameter:
// Illuminate/Routing/UrlGenerator.php:365,373
$parameters = $parameters + ['expires' => $this->availableAt($expiration)];
...
'signature' => hash_hmac('sha256', $this->route($name, $parameters, $absolute), $key),
The name is hardcoded and reserved — Laravel throws InvalidArgumentException if an application tries to use signature or expires as a route parameter (UrlGenerator.php:391,460). There is no configuration option.
So the value that authorises the request is captured in the span, and remains replayable until expires. This affects every Laravel application using this instrumentation, not a particular configuration.
Expected behaviour per the semantic conventions
The requirement is already vendored into this project as PHPDoc on the very constant the instrumentation sets — sem-conv/Attributes/UrlAttributes.php, above const URL_FULL:
Sensitive content provided in
url.fullSHOULD be scrubbed when instrumentations can identify it.Query string values for the following keys SHOULD be redacted by default and replaced by the value
REDACTED:
AWSAccessKeyIdSignaturesigX-Goog-SignatureWhen a query string value is redacted, the query string key SHOULD still be preserved, e.g.
https://www.example.com/path?color=blue&sig=REDACTED.
The URL attribute registry places this on the instrumentation, and notes instrumentations MAY allow the list to be overridden.
Current state
grep -riE 'scrub|sanitiz|redact' --include='*.php' across open-telemetry/sdk, open-telemetry/api, open-telemetry/sem-conv and opentelemetry-auto-laravel returns matches only inside PHPDoc comments in sem-conv, plus SanitizeCombinedHeadersPropagationGetter in context, which concerns combined header values rather than URLs.
There appears to be no executable query-parameter redaction anywhere in the PHP implementation, and no configuration surface for it. Userinfo is handled only in ClientRequestWatcher, and not on server spans.
Question: is key matching intended to be case-sensitive?
The default list contains Signature (capitalised, from the AWS S3 query-auth docs). Laravel emits lowercase signature. A case-insensitive implementation would cover Laravel out of the box; a case-sensitive one would not.
The specification does not appear to state this. Clarifying it would be valuable, since the difference decides whether the most widely used PHP framework's signed URLs are protected by the default list or need an override.
Reproduction
- Laravel 12 app with
open-telemetry/opentelemetry-auto-laravelandOTEL_PHP_AUTOLOAD_ENABLED=true - Define a signed route and generate a link with
URL::temporarySignedRoute('verify', now()->addMinutes(60), ['id' => 1]) - Request the URL and inspect the exported span
url.full contains the complete ?expires=…&signature=….
Suggested fix
- Redact the documented default keys in both
Kernel.php(server spans) andClientRequestWatcher.php(client spans), preserving keys and replacing values withREDACTED. - Consider a shared helper in
open-telemetry/sdk, since every instrumentation settingurl.fullorurl.queryneeds identical behaviour. - Expose an override so applications can add framework-specific keys —
signaturefor Laravel, if matching turns out to be case-sensitive. - Clarify case-sensitivity in the specification, or handle it case-insensitively.
Happy to open a PR if the maintainers agree on the approach and where the helper should live.
Environment
open-telemetry/opentelemetry-auto-laravel |
1.8.0 |
open-telemetry/sdk |
1.15.0 |
open-telemetry/api |
1.10.0 |
laravel/framework |
v12.64.0 |
| PHP | 8.4 |
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.