fix: enforce 0600 permissions on .netrc credentials file

The previous use of `touch` before `netrc set` allowed the file to inherit the umask and be world-readable, exposing stored git credentials to local users. The set and unset paths now explicitly chmod 0600 and chown to the dokku user, and the plugin install hook repairs permissions on already-affected installations.
This commit is contained in:
Jose Diaz-Gonzalez
2026-05-09 12:22:17 -04:00
parent 2974830e8f
commit 6eb8b8632c
3 changed files with 96 additions and 2 deletions

View File

@@ -14,6 +14,17 @@ trigger-git-install() {
fn-plugin-property-setup "git"
migrate_git_vars_0_12_0 "$@"
migrate_netrc_permissions "$@"
}
migrate_netrc_permissions() {
declare desc="enforces 0600 permissions on a pre-existing .netrc from older dokku versions"
local netrc_file="${DOKKU_ROOT}/.netrc"
[[ ! -f "$netrc_file" ]] && return 0
chmod 600 "$netrc_file"
chown "${DOKKU_SYSTEM_USER}:${DOKKU_SYSTEM_GROUP}" "$netrc_file"
}
migrate_git_vars_0_12_0() {

View File

@@ -86,12 +86,21 @@ cmd-git-auth() {
if [[ -z "$USERNAME" ]]; then
dokku_log_info1 "Removing netrc auth entry for host $HOST"
netrc unset "$HOST"
return $?
local exit_code=$?
fn-git-auth-secure-netrc
return $exit_code
fi
dokku_log_info1 "Setting netrc auth entry for host $HOST"
touch "${DOKKU_ROOT}/.netrc"
netrc set "$HOST" "$USERNAME" "$PASSWORD"
fn-git-auth-secure-netrc
}
fn-git-auth-secure-netrc() {
declare desc="enforces 0600 permissions and dokku ownership on the netrc file"
[[ ! -f "${DOKKU_ROOT}/.netrc" ]] && return 0
chmod 600 "${DOKKU_ROOT}/.netrc"
chown "${DOKKU_SYSTEM_USER:-dokku}:${DOKKU_SYSTEM_GROUP:-dokku}" "${DOKKU_ROOT}/.netrc"
}
cmd-git-auth-status() {

View File

@@ -105,6 +105,80 @@ teardown() {
echo "status: $status"
assert_success
assert_output_contains "piped-username:piped-password"
run /bin/bash -c "stat -c '%a' ${DOKKU_ROOT}/.netrc"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "600"
run /bin/bash -c "stat -c '%U:%G' ${DOKKU_ROOT}/.netrc"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "dokku:dokku"
}
@test "(git) git:auth repairs world-readable .netrc" {
run /bin/bash -c "chmod 644 ${DOKKU_ROOT}/.netrc"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "stat -c '%a' ${DOKKU_ROOT}/.netrc"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "644"
run /bin/bash -c "dokku git:auth github.com username password"
echo "output: $output"
echo "status: $status"
assert_success
assert_output_contains "Setting netrc auth entry for host github.com"
run /bin/bash -c "stat -c '%a' ${DOKKU_ROOT}/.netrc"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "600"
run /bin/bash -c "stat -c '%U:%G' ${DOKKU_ROOT}/.netrc"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "dokku:dokku"
}
@test "(git) git:auth unset preserves 0600 on remaining .netrc" {
run /bin/bash -c "dokku git:auth github.com username password"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku git:auth other.example.com user2 pass2"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "chmod 644 ${DOKKU_ROOT}/.netrc"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku git:auth github.com"
echo "output: $output"
echo "status: $status"
assert_success
assert_output_contains "Removing netrc auth entry for host github.com"
if [[ -f "${DOKKU_ROOT}/.netrc" ]]; then
run /bin/bash -c "stat -c '%a' ${DOKKU_ROOT}/.netrc"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "600"
fi
}
@test "(git) git:auth-status" {