The Tracking-Link Bug That Breaks Signed URLs

A bug can hide in your code for a long time. It works for most links. It stays silent for marketing links. But it breaks the links that matter most.

I found this bug in my tool, mail-history. It breaks signed URLs. These are links used for email verification or secure downloads.

Here is how it happened.

My tool rewrites email HTML to track clicks. It takes the original URL, encrypts it, and turns it into a tracking link. When a user clicks, the tool decrypts the URL and sends them to the real destination.

The problem started when I pulled the URL from the rendered HTML.

Laravel and Blade escape HTML attributes. An ampersand in a URL becomes an HTML entity. It turns from & into &.

For a standard link, a browser fixes this automatically. You never notice the difference.

But my tool does not send the link to a browser. It sends the string to a decryption function.

If your signed URL looks like this: https://example.com/verify?expires=123&signature=abc

The HTML looks like this: https://example.com/verify?expires=123&signature=abc

My tool encrypts the version with &. When the user clicks, the tool decrypts it and sends them to the version with &.

Laravel sees the & and thinks the signature is wrong. The verification fails.

The fix is one line of code. I use html_entity_decode to turn & back into & before the encryption happens.

This ensures the decrypted URL matches the original signed URL byte for byte.

A lesson for your work:

  • If you pull data from rendered HTML to use in a function, assume it is escaped.
  • Browsers forgive mistakes. Encryption and signature validation do not.
  • When you use a one-line fix, write a test for it.

I wrote a test that specifically checks for the presence of &. If a future developer removes my fix during a cleanup, the test will fail immediately.

Source: https://dev.to/nasrulhazim/the-tracking-link-bug-that-only-breaks-signed-urls-38c