Update as at Summer'13: New Feature: Require CSRF protection on GET requests
Since Summer'13 Salesforce have started what looks like a feature to start to address this. Through a checkbox on the Visualforce page metadata called 'Require CSRF protection on GET requests'. When enabled it will ensure your page cannot be used via a GET request without a token generated by Salesforce. Currently only the Delete actions on custom objects support this, but its a start! I've made a request within Salesforce to understand the rollout of this feature, hopefully we will see it for all Custom Buttons soon!
Select Require CSRF protection on GET requests to enable Cross Site Request Forgery (CSRF) protection for GET requests for the page. When checked, it protects against CSRF attacks by modifying the page to require a CSRF confirmation token, a random string of characters in the URL parameters. With every GET request, Visualforce checks the validity of this string of characters and doesn’t load the page unless the value found matches the value expected.
Check this box if the page performs any DML operation when it’s initially loaded. When checked, all links to this page need a CSRF token added to the URL query string parameters. This checkbox is available for pages set to API version 28.0 and later.
In Summer ’13, the only way to add a valid CSRF token to a URL is to override an object’s standard Delete link with a Visualforce page. The Delete link will automatically include the required token. Don’t check this box for any page that doesn’t override an object’s standard Delete link.
As per the definition of this security issue here. The concern is that another page outside of Salesforce or even within it, can make a HTTP GET request to the URL of your page and result in an update to the database without the end user knowing or accepting it. If your code simply performed database SOQL operations in Apex there would be no issue here. You may be able to discuss this with the security team as 'false positive' use case however, if you can convince them its none critical update in respect to your application.
From your statement 'this method that is executed on page action' it sounds like the method is called during the page load (via 'action' attribute on apex:page) and hence would be a result of a HTTP GET then this is likely what it is calling out. As it's observed the link between the method and the reference in the action attribute. It may also be referring to the use of ApexPages.currentPage().getParameters() as well.
Some thoughts to consider...
- Change your page to invoke the action from a apex:commandbutton (as apposed to page load) and if possible utilise the StandardController to obtain the ID. This way your user is making a HTTP POST (via apex:commandButton) to your logic and your also leveraging the platform to determine the page context (the Id). The downside of this, is that this approach impacts your user experience with an additional button.
- Consider embedding your page in the layout of your object, it maybe a simple page to invoke your existing page. But this way Salesforce's own CSRF protection kicks in. The downside to this is the lack of customisation of your button amongst the others and the fact that it is positioned visually in a different place then usual.
- Implement your own CSRF protection, not recommended, and I've yet to see a good implementation of this that is stable enough (against platform changes) to trust in production code.
In short there is no ideal way to keep what is a good platform feature for binding Custom Button's to Apex code that performs updates. Here are some links to other discussions and ideas on this issue. There is also a Salesforce Idea to enhance Custom Buttons to support this which you can upvote.
Hope this helps!