Cross Site Request Forgery in Chi with Dynamodb
Cross Site Request Forgery in Chi with Dynamodb — how this specific combination creates or exposes the vulnerability
Cross Site Request Forgery (CSRF) in a Chi application that uses Amazon DynamoDB can occur when an authenticated user is tricked into issuing unintended requests to a state-changing endpoint. Because Chi is a Clojure web framework that typically relies on session cookies for authentication, an attacker can craft a malicious HTML form or script hosted on a different origin that submits requests to your Chi routes. If the application does not implement anti-CSRF protections such as synchronizer tokens or same-site cookies, the browser automatically includes the session cookie, and the server processes the request with the user’s privileges.
When the Chi handler performs write operations against DynamoDB—such as updating a user profile, creating a record, or changing an access control setting—the attacker’s forged request can directly mutate data in DynamoDB. For example, a route like /update-email that accepts POST parameters and calls the DynamoDB client to update an item becomes dangerous if it only relies on session cookies for authorization without verifying intent. The DynamoDB operations are executed under the permissions of the compromised user’s credentials, potentially leading to unauthorized updates, data leakage, or privilege escalation if the IAM policy attached to the application’s credentials is overly permissive.
Additionally, if the Chi application exposes an unauthenticated or weakly authenticated API endpoint that writes to DynamoDB, and that endpoint is also invoked by an embedded image tag or script from a malicious site, the browser may trigger a GET or POST request automatically. Since DynamoDB operations like UpdateItem or PutItem are typically not idempotent or safe, this can result in unintended record creation or modification. The combination of Chi’s session-based authentication, missing CSRF tokens or anti-CSRF headers, and direct DynamoDB mutations creates a clear path for attackers to exploit trust relationships in the browser and backend service.
Moreover, if the application uses query parameters or header values to determine which DynamoDB item to modify (for example, an unvalidated user_id in the URL), an attacker can manipulate these inputs within the forged request to target other users’ resources. This is especially risky when combined with insufficient authorization checks on the server side, as the request may pass basic authentication but fail to enforce proper ownership verification against DynamoDB. The server-side handler must therefore treat every request as potentially forged and validate intent, identity, and permissions before performing any DynamoDB write operations.
Dynamodb-Specific Remediation in Chi — concrete code fixes
To mitigate CSRF risks in Chi when interacting with DynamoDB, implement anti-CSRF tokens on all state-changing POST routes and enforce strict same-site cookie policies. For DynamoDB operations, ensure that each request includes explicit authorization checks that validate the requesting user’s identity against the item being modified, rather than relying solely on session cookies.
Chi route with CSRF protection and DynamoDB write
Use middleware to generate and validate anti-CSRF tokens, and include the user ID in both the token and the DynamoDB condition expression to guarantee ownership.
(ns myapp.handlers
(:require [cheshire.core :as json]
[clojure.string :as str]
[buddy.core.codecs :as codecs]
[buddy.sign.jwt :as jwt]
[aws.sdk.dynamodb :as ddb]))
(defn generate-csrf-token [user-id secret]
(jwt/sign {:user-id user-id :exp (System/currentTimeMillis)} secret))
(defn verify-csrf-token [token secret]
(try
(jwt/verify token secret)
(catch Exception _ nil)))
(def csrf-secret "super-secret-key-change-in-prod")
(defn update-email-handler [request]
(let [session (:session request)
user-id (:user-id session)
csrf-token (get-in request [:params :csrf-token])
new-email (get-in request [:params :email])]
(if (and user-id csrf-token)
(let [valid-token? (= user-id (get-in (verify-csrf-token csrf-token csrf-secret) [:user-id]))]
(if valid-token?
(do
(ddb/update-item :users
{:key {:user-id (str user-id)}
:update-expression "set #email = :val"
:expression-attribute-names {"#email" "email"}
:expression-attribute-values {":val" new-email}
:condition-expression "attribute_exists(user-id)"})
{:status 200 :body (json/generate-string {:message "Email updated"})})
{:status 403 :body (json/generate-string {:error "Invalid CSRF token"})}))
{:status 401 :body (json/generate-string {:error "Unauthorized"})}))
(defn app [request]
(case (:request-method request)
:post (update-email-handler request)
:get {:status 200 :body "OK"})))
Ensure your session cookies are configured with :same-site and :secure flags:
(defonce session-store
(cookie-store/fetch-cookie-store {:cookie-attrs {:http-only true :same-site :strict :secure true}}))
On the DynamoDB side, use condition expressions to enforce ownership and avoid relying on the client-supplied identifier alone. For example, when updating an item, include a condition that the partition key matches the authenticated user ID, ensuring that even if an attacker forges a request, the update will fail if the item does not belong to them.
IAM and application-level best practices
Limit IAM permissions for the Chi application to the minimum required actions on DynamoDB tables, and scope resources by user-specific tags or partition keys. Combine this with per-request ownership checks and anti-CSRF tokens to create defense-in-depth against Cross Site Request Forgery in Chi applications that persist data to DynamoDB.