diff --git a/frontend.py b/frontend.py
index 452769f..7fbf975 100755
--- a/frontend.py
+++ b/frontend.py
@@ -178,9 +178,10 @@ def register_telegram(user):
     return city_page(user.get_city(), info="Thanks for registering Telegram!")
 
 
-@get('/api/state')
-def api_enable(user):
-    return user.state()
+# unused afaik
+#@get('/api/state')
+#def api_enable(user):
+#    return user.state()
 
 
 @get('/static/<filename:path>')
@@ -197,6 +198,7 @@ def guides(filename):
 def logout():
     # clear auth cookie
     response.set_cookie('uid', '', expires=0, path="/")
+    response.set_cookie('csrf', '', expires=0, path="/")
     # :todo show info "Logout successful."
     redirect('/')
 
diff --git a/photo-1461685265823-f8d5d0b08b9b?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&dl=matthew-henry-87142-unsplash.jpg b/photo-1461685265823-f8d5d0b08b9b?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&dl=matthew-henry-87142-unsplash.jpg
deleted file mode 100644
index 1b546db..0000000
Binary files a/photo-1461685265823-f8d5d0b08b9b?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&dl=matthew-henry-87142-unsplash.jpg and /dev/null differ
diff --git a/session.py b/session.py
index 5d0c263..ccda7bb 100644
--- a/session.py
+++ b/session.py
@@ -1,4 +1,4 @@
-from bottle import redirect, request
+from bottle import redirect, request, abort, response
 from db import db
 from functools import wraps
 from inspect import Signature
@@ -17,10 +17,14 @@ class SessionPlugin(object):
         if self.keyword in Signature.from_callable(route.callback).parameters:
             @wraps(callback)
             def wrapper(*args, **kwargs):
-                uid = request.get_cookie('uid', secret=db.secret)
+                uid = request.get_cookie('uid', secret=db.get_secret())
                 if uid is None:
                     return redirect(self.loginpage)
                 kwargs[self.keyword] = User(uid)
+                if request.method == 'POST':
+                    if request.forms['csrf'] != request.get_cookie('csrf',
+                                                        secret=db.get_secret()):
+                        abort(400)
                 return callback(*args, **kwargs)
 
             return wrapper
diff --git a/template/settings.tpl b/template/settings.tpl
index dae30ce..66cf873 100644
--- a/template/settings.tpl
+++ b/template/settings.tpl
@@ -61,6 +61,7 @@
                 <option value='octodon.social'>
                 <option value='soc.ialis.me'>
             </datalist>
+            <input name='csrf' value='{{csrf}}' type='hidden' />
             <input name='confirm' value='Log in' type='submit'/>
         </form>
 </section>
@@ -82,6 +83,7 @@
     </p>
     <form action="/settings/telegram" method="post">
         <input type="text" name="apikey" placeholder="Telegram bot API key" id="apikey">
+        <input name='csrf' value='{{csrf}}' type='hidden' />
         <input name='confirm' value='Login with Telegram' type='submit'/>
     </form>
 </div>
@@ -106,6 +108,7 @@
     </p>
     <form action="/settings/markdown" method="post">
         <textarea id="markdown" rows="20" cols="70" name="markdown" wrap="physical">{{markdown}}</textarea>
+        <input name='csrf' value='{{csrf}}' type='hidden' />
         <input name='confirm' value='Save' type='submit'/>
     </form>
 </div>
@@ -123,6 +126,7 @@
     </p>
     <form action="/settings/mail_md" method="post">
         <textarea id="mail_md" rows="20" cols="70" name="mail_md" wrap="physical">{{mail_md}}</textarea>
+        <input name='csrf' value='{{csrf}}' type='hidden' />
         <input name='confirm' value='Save' type='submit'/>
     </form>
 </div>
@@ -137,6 +141,7 @@
     </p>
     <form action="/settings/goodlist" method="post">
         <textarea id="goodlist" rows="8" cols="70" name="goodlist" wrap="physical">{{triggerwords}}</textarea>
+        <input name='csrf' value='{{csrf}}' type='hidden' />
         <input name='confirm' value='Submit' type='submit'/>
     </form>
 </div>
@@ -151,6 +156,7 @@
     </p>
     <form action="/settings/blocklist" method="post">
         <textarea id="blocklist" rows="8" cols="70" name="blocklist" wrap="physical">{{badwords}}</textarea>
+        <input name='csrf' value='{{csrf}}' type='hidden' />
         <input name='confirm' value='Submit' type='submit'/>
     </form>
 </div>
diff --git a/user.py b/user.py
index 92eb463..147fb40 100644
--- a/user.py
+++ b/user.py
@@ -1,9 +1,10 @@
 from config import config
-from bottle import response
+from bottle import response, request
 from db import db
 import jwt
 from mastodon import Mastodon
 from pylibscrypt import scrypt_mcf, scrypt_mcf_check
+from os import urandom
 
 
 class User(object):
@@ -11,6 +12,13 @@ class User(object):
         # set cookie
         response.set_cookie('uid', uid, secret=db.get_secret(), path='/')
         self.uid = uid
+        response.set_cookie('csrf', self.get_csrf(), db.get_secret(), path='/')
+
+    def get_csrf(self):
+        csrf_token = request.get_cookie('csrf', secret=db.get_secret())
+        if not csrf_token:
+            csrf_token = str(urandom(32))
+        return csrf_token
 
     def check_password(self, password):
         db.execute("SELECT passhash FROM user WHERE id=?;", (self.uid,))
@@ -235,6 +243,7 @@ schlitz
         # - mail_md
         # - goodlist
         # - blocklist
+        # - csrf
         # - logged in with twitter?
         # - logged in with mastodon?
         # - enabled?
@@ -244,7 +253,8 @@ schlitz
                     mail_md=citydict['mail_md'],
                     triggerwords=self.get_trigger_words(),
                     badwords=self.get_badwords(),
-                    enabled=self.enabled)
+                    enabled=self.enabled,
+                    csrf=self.get_csrf())
 
     def save_request_token(self, token):
         db.execute("""INSERT INTO