In general, if you have an XSS vulnerability in your app, you can't have proper protection against CSRF, either. Every single line of JS that executes on your page should be your own, otherwise it'll be impossible to distinguish CSRF requests from genuine requests. So there's no point worrying about JS on your own page having access to the CSRF token. Likewise, if your pages are unencrypted, you don't have control over anything that appears or executes on your page.<p>Provided that there are no XSS vulnerabilities (e.g. you use a framework that automatically escapes everything you put in a template) and you use SSL on all your pages, an easy way to do "stateless" CSRF protection is to insert a token into each form that contains encrypted information about the form and the client. For example, create an array containing a unique identifier of the form, the client's IP address, the client's user agent string, and any other piece of information that is available with every request (so that you don't have to remember them). Serialize the array and encrypt it with AES using a key that you keep in the server. When you receive a POST, decrypt the token and check if the information it contains matches the client's details. If it matches, you know that it was you who generated that token. Of course this is vulnerable to replay attacks, but if your app is XSS-proof and your pages are delivered over SSL, it should be very difficult for an attacker to obtain the token in the first place.<p>But realistically, if you're already using cookies, there's no point insisting on a stateless solution to anything. If your site has a login functionality at all, you're probably already restricting dangerous actions to logged-in users only. In that case, spare a few bytes in your session storage. Generate a random token, put it in your form, and also store it in the session. Remove it from the session after use. Problem solved, and no replay attacks either. Why the obsession with stateless stuff? Maintaining state is easier than ever before. Gone are the days when sessions were incompatible with load balancing. Nowadays you can just throw all your sessions in a Redis node and access them in a fraction of a millisecond from a thousand different servers.<p>Edit: There are also in-between solutions if you really want to avoid using sessions. For example, you could keep a database of all the tokens you ever generated, from which tokens are deleted when used. This can help you prevent replays while minimizing (but not eliminating) state. If you don't want the database to grow indefinitely, you can just say "all tokens expire after X hours" and periodically purge old entries from your database.