diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..0b26d977
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,5 @@
+dijkstra/.local/libexec/cron/backup filter=redact
+common/.config/elia/config.toml filter=redact
+common/.config/nvim/lua/config/secrets.lua filter=redact
+common/.config/git/credentials filter=redact
+common/.local/bin/openproject_hours filter=redact
diff --git a/common/.config/git/config b/common/.config/git/config
index 96b60c17..7268924b 100644
--- a/common/.config/git/config
+++ b/common/.config/git/config
@@ -23,6 +23,10 @@
 	smudge = git-lfs smudge -- %f
 	process = git-lfs filter-process
 	required = true
+[filter "redact"]
+    clean = ~/.local/libexec/redact_git_filter clean
+    smudge = ~/.local/libexec/redact_git_filter smudge
+    required = true
 [diff]
     colorMoved = default
 [core]
diff --git a/common/.local/libexec/redact_git_filter b/common/.local/libexec/redact_git_filter
new file mode 100755
index 00000000..f4e22760
--- /dev/null
+++ b/common/.local/libexec/redact_git_filter
@@ -0,0 +1,14 @@
+#!/bin/sh
+# shellcheck disable=SC2016
+
+FS="$(printf '\033')"
+GS="$(printf '\034')"
+
+map=$(jq -r 'to_entries[] | "\(.key)'"$FS"'\(.value)"' "${HOME}/.secrets/dotfile-secrets.json")
+
+case $1 in
+    clean) awk='{printf "s%s%s%s<#%s#>%sg;", d, $2, d, $1, d }' ;;
+    smudge) awk='{printf "s%s<#%s#>%s%s%sg;", d, $1, d, $2, d }' ;;
+esac
+
+sed "$(echo "$map" | awk -F"$FS" -v d="$GS" "$awk")"