Security Tip: Stop Putting Actions on GET Requests!

[Tip #128] Do you know the difference between GET and POST requests, and why it's so important that GET requests only ever retrieve data?

Security Tip: Stop Putting Actions on GET Requests!
๐Ÿ’ก
Note, I'll just be using POST in this article to keep things simple, but I am talking about all four: POST, PUT, PATCH, and DELETE.

Let me ask you a question:

What is the difference between GET and POST?

You're probably thinking something along the lines of:

GET requests retrieve data from the server, while POST requests send data to the server and perform actions. Links use GET requests and forms use POST requests.

But what about this question:

What is the technical difference between GET and POST?

Similar to the above, you're probably thinking:

GET requests can be made entirely from a URL and triggered through links, while POST requests need to be submitted through a form submission, Javascript, or an API request.

While the first answer talks about the flow of data (GET - retrieve, POST - store) and notes that POST requests can perform actions, the second answer makes no mention of actions or security in general.

Which brings us to the final question:

What is the difference in security between GET and POST?

GET requests can be triggered from unsafe contexts and should never be trusted to perform actions, while POST requests have a lot of protections provided by the browser so you can use them safely (mostly).

Since I think that deserves more of an explanation, let's look at all the ways GET and POST requests can be triggered maliciously without Cross-Site Scripting (XSS):

GET requests:

  1. Can be triggered by third-party sites through links (<a>) that the victim clicks on.
  2. Can be triggered by third-party sites through resources (<img>, <video>, etc) that load within the victim's browser.
  3. Can be triggered by third-party sites through frames (<iframe>) that load with the victim's browser.
  4. Can be triggered through links sent via Direct Messages, Social Media, Email, Chat clients, etc, to the victim's device.
  5. Can be triggered through seemingly safe tags (<a>, <img>, etc) inside user submitted content on your website. (It's not XSS, so your site will load it!)
  6. Can be triggered through seemingly safe Markdown as user submitted content on your website. (Like #5, it's not XSS, so it'll load!)
  7. Can be hidden and triggered through redirects and URL shorteners.
  8. And a few more creative ways...

Conversely, POST requests:

  1. Can be triggered from a <form> on your site, IF you allow users to generate an entire <form> inside their submitted content and render it on the page for them... ๐Ÿคจ
  2. Can be triggered by XSS Nevermind, I said no XSS above...
  3. Can be triggered from a third-party site if you disable CSRF and SameSite protections and/or misconfigure CORS... ๐Ÿ˜ฑ

Or to reduce the last 400 words down into a single sentence:

Don't perform actions or state-changing operations on GET requests, it's not safe!

So go through your apps and check none of your actions are performed via GET, even if behind an auth layer. It's an open invitation waiting to be abused.


If you found this security tip useful? ๐Ÿ‘
Subscribe now to get weekly Security Tips straight to your inbox, filled with practical, actionable advice to help you build safer apps.

Want to learn more? ๐Ÿค“
Upgrade to a Premium Subscription for exclusive monthly In Depth articles, or support my work with a one-off tip! Your support directly funds my security work in the Laravel community. ๐Ÿฅฐ

Need a second set of eyes on your code?
Book in a
Laravel Security Audit and Penetration Test today! I also offer budget-friendly Security Reviews too.

Finally, connect with me on Bluesky, or other socials.