diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b5f98037f5a942a893e673927912ac27a86e0a4a
--- /dev/null
+++ b/.github/workflows/security.yml
@@ -0,0 +1,35 @@
+name: 'Run Security Tests'
+on:
+  push:
+    branches:
+      - main
+      - dev
+  pull_request:
+  schedule:
+    - cron: '* * * * 0' # run weekly
+
+permissions:
+  contents: read
+  actions: read
+  checks: write
+  security-events: write
+
+jobs:
+  report:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+
+      - name: Run Trivy vulnerability scanner in repo mode
+        uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5 # 0.30.0
+        with:
+          scan-type: 'fs'
+          format: 'sarif'
+          output: 'trivy-results-fs.sarif'
+          severity: 'CRITICAL,HIGH,MEDIUM'
+
+      - name: Upload Trivy scan results to GitHub Security tab
+        uses: github/codeql-action/upload-sarif@45775bd8235c68ba998cffa5171334d58593da47 # v3
+        with:
+          sarif_file: 'trivy-results-fs.sarif'