diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb
index c764b45101..135c575658 100644
--- a/app/controllers/api/base_controller.rb
+++ b/app/controllers/api/base_controller.rb
@@ -7,6 +7,7 @@ class Api::BaseController < ApplicationController
   include RateLimitHeaders
   include AccessTokenTrackingConcern
   include ApiCachingConcern
+  include Api::ContentSecurityPolicy
 
   skip_before_action :require_functional!, unless: :limited_federation_mode?
 
@@ -17,26 +18,6 @@ class Api::BaseController < ApplicationController
 
   protect_from_forgery with: :null_session
 
-  content_security_policy do |p|
-    # Set every directive that does not have a fallback
-    p.default_src :none
-    p.frame_ancestors :none
-    p.form_action :none
-
-    # Disable every directive with a fallback to cut on response size
-    p.base_uri false
-    p.font_src false
-    p.img_src false
-    p.style_src false
-    p.media_src false
-    p.frame_src false
-    p.manifest_src false
-    p.connect_src false
-    p.script_src false
-    p.child_src false
-    p.worker_src false
-  end
-
   rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e|
     render json: { error: e.to_s }, status: 422
   end
diff --git a/app/controllers/concerns/api/content_security_policy.rb b/app/controllers/concerns/api/content_security_policy.rb
new file mode 100644
index 0000000000..8116dca57b
--- /dev/null
+++ b/app/controllers/concerns/api/content_security_policy.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Api::ContentSecurityPolicy
+  extend ActiveSupport::Concern
+
+  included do
+    content_security_policy do |policy|
+      # Set every directive that does not have a fallback
+      policy.default_src :none
+      policy.frame_ancestors :none
+      policy.form_action :none
+
+      # Disable every directive with a fallback to cut on response size
+      policy.base_uri false
+      policy.font_src false
+      policy.img_src false
+      policy.style_src false
+      policy.media_src false
+      policy.frame_src false
+      policy.manifest_src false
+      policy.connect_src false
+      policy.script_src false
+      policy.child_src false
+      policy.worker_src false
+    end
+  end
+end
diff --git a/spec/requests/api/v1/csp_spec.rb b/spec/requests/api/v1/csp_spec.rb
new file mode 100644
index 0000000000..2db52ac725
--- /dev/null
+++ b/spec/requests/api/v1/csp_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'API namespace minimal Content-Security-Policy' do
+  before { stub_tests_controller }
+
+  after { Rails.application.reload_routes! }
+
+  it 'returns the correct CSP headers' do
+    get '/api/v1/tests'
+
+    expect(response).to have_http_status(200)
+    expect(response.headers['Content-Security-Policy']).to eq(minimal_csp_headers)
+  end
+
+  private
+
+  def stub_tests_controller
+    stub_const('Api::V1::TestsController', api_tests_controller)
+
+    Rails.application.routes.draw do
+      get '/api/v1/tests', to: 'api/v1/tests#index'
+    end
+  end
+
+  def api_tests_controller
+    Class.new(Api::BaseController) do
+      def index
+        head 200
+      end
+
+      private
+
+      def user_signed_in? = false
+      def current_user = nil
+    end
+  end
+
+  def minimal_csp_headers
+    "default-src 'none'; frame-ancestors 'none'; form-action 'none'"
+  end
+end