fix remote auth and danger guard

This commit is contained in:
Xiaoxukuaipao committed 2026-05-16 21:32:02 -07:00
1 parent 2fa77e3ef7
commit e35a20bceb
2 files changed
+174 -28

No files matched your search

@@ -1,6 +1,6 @@
{
"name": "autodl-remote",
"version": "0.6.0",
"version": "0.6.1",
"description": "Bash-only SSH account, command, upload, download, job, and shutdown tool layer for AutoDL.",
"author": {
"name": "haibarazz",
+173 -27
View File
@@ -305,6 +305,15 @@ ssh_common_args() {
fi
}
scp_common_args() {
SCP_ARGS=(-P "$ACCOUNT_PORT" -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o ControlMaster=auto -o ControlPersist=600 -o "ControlPath=$APP_DIR/ssh-%C")
mkdir -p "$APP_DIR"
[ -n "$ACCOUNT_KEY" ] && SCP_ARGS+=(-i "$ACCOUNT_KEY")
if [ "$ACCOUNT_AUTH" != "keychain" ] && [ "$ACCOUNT_AUTH" != "prompt" ]; then
SCP_ARGS+=(-o BatchMode=yes)
fi
}
rsync_ssh_command() {
local cmd
cmd="ssh -p $(shell_quote "$ACCOUNT_PORT") -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o ControlMaster=auto -o ControlPersist=600 -o ControlPath=$(shell_quote "$APP_DIR/ssh-%C")"
@@ -324,7 +333,7 @@ expect_with_password() {
command -v expect >/dev/null 2>&1 || die "Account uses keychain auth, but expect is not available."
local password="$1"
shift
AUTODL_REMOTE_PASSWORD="$password" expect -c '
AUTODL_REMOTE_PASSWORD="$password" expect -f /dev/stdin "$@" <<'EXPECT'
set timeout -1
set password $env(AUTODL_REMOTE_PASSWORD)
spawn {*}$argv
@@ -341,7 +350,7 @@ expect_with_password() {
}
catch wait result
exit [lindex $result 3]
' "$@"
EXPECT
}
run_transport() {
@@ -423,19 +432,151 @@ upload_local_file() {
local local_path="$1" remote_path="$2"
[ -f "$local_path" ] || die "Local script does not exist or is not a file: $local_path"
ensure_remote_dir "$(dirname "$remote_path")"
scp_common_args
run_transport scp "${SCP_ARGS[@]}" "$local_path" "$ACCOUNT_TARGET:$remote_path"
}
upload_stdin_to_remote() {
local remote_path="$1"
ensure_remote_dir "$(dirname "$remote_path")"
ssh_common_args
local scp_args=(-P "$ACCOUNT_PORT")
[ -n "$ACCOUNT_KEY" ] && scp_args+=(-i "$ACCOUNT_KEY")
run_transport scp "${scp_args[@]}" "$local_path" "$ACCOUNT_TARGET:$remote_path"
run_transport ssh "${SSH_ARGS[@]}" "$ACCOUNT_TARGET" "cat > $(shell_quote "$remote_path")"
}
upload_file_via_ssh() {
local local_path="$1" remote_path="$2"
[ -f "$local_path" ] || die "Local script does not exist or is not a file: $local_path"
upload_stdin_to_remote "$remote_path" < "$local_path"
}
strip_token_quotes() {
local value="$1"
value="${value%\"}"
value="${value#\"}"
value="${value%\'}"
value="${value#\'}"
printf '%s\n' "$value"
}
is_dangerous_rm_target() {
local target="$1" recursive="$2" cwd="${3:-$REMOTE_ROOT}" project_root autodl_tmp
target="$(strip_token_quotes "$target")"
[ -n "$target" ] || return 1
project_root="${REMOTE_ROOT%/}"
autodl_tmp="/root/autodl-tmp"
case "$target" in
"\$REMOTE_ROOT"|"\${REMOTE_ROOT}"|"\$PWD"|"\${PWD}") return 0 ;;
esac
[ "$target" = "/" ] && return 0
[ "$target" = "/*" ] && return 0
if [ "$recursive" = "true" ]; then
case "$target" in
"."|"./"|"./*"|"*"|"~"|"~/"|"~/*") return 0 ;;
esac
fi
while [ "${target%/}" != "$target" ] && [ "$target" != "/" ]; do
target="${target%/}"
done
if [ "$target" = "$project_root" ]; then
return 0
fi
if [ "$target" = "$project_root/*" ]; then
return 0
fi
if [ "$target" = "$autodl_tmp" ] || [ "$target" = "$autodl_tmp/*" ]; then
return 0
fi
if [ "$recursive" = "true" ] && [ "$target" = "$cwd" ]; then
return 0
fi
return 1
}
contains_dangerous_rm() {
local cmd="$1" cwd="${2:-$REMOTE_ROOT}" line token recursive
while IFS= read -r line; do
set -- $line
while [ $# -gt 0 ]; do
token="$(strip_token_quotes "$1")"
case "$token" in
sudo|command|builtin|nohup) shift ;;
env) shift; while [ $# -gt 0 ]; do case "$1" in *=*) shift ;; *) break ;; esac; done ;;
*=*) shift ;;
*) break ;;
esac
done
token="$(strip_token_quotes "${1:-}")"
[ "${token##*/}" = "rm" ] || continue
shift
recursive=false
while [ $# -gt 0 ]; do
token="$1"
shift
case "$token" in
--) break ;;
--*) continue ;;
-*) case "$token" in *r*|*R*) recursive=true ;; esac; continue ;;
esac
is_dangerous_rm_target "$token" "$recursive" "$cwd" && return 0
done
while [ $# -gt 0 ]; do
token="$1"
shift
is_dangerous_rm_target "$token" "$recursive" "$cwd" && return 0
done
done <<EOF
$(printf '%s\n' "$cmd" | sed 's/[;&|]/\
/g')
EOF
return 1
}
contains_dangerous_system_command() {
local cmd="$1" line token command_name
while IFS= read -r line; do
set -- $line
while [ $# -gt 0 ]; do
token="$(strip_token_quotes "$1")"
case "$token" in
sudo|command|builtin|nohup) shift ;;
env) shift; while [ $# -gt 0 ]; do case "$1" in *=*) shift ;; *) break ;; esac; done ;;
*=*) shift ;;
*) break ;;
esac
done
[ $# -gt 0 ] || continue
token="$(strip_token_quotes "$1")"
command_name="${token##*/}"
case "$command_name" in
shutdown|reboot|poweroff|halt|mkfs|mkfs.*)
return 0
;;
dd)
shift
while [ $# -gt 0 ]; do
token="$(strip_token_quotes "$1")"
case "$token" in if=*) return 0 ;; esac
shift
done
;;
esac
done <<EOF
$(printf '%s\n' "$cmd" | sed 's/[;&|]/\
/g')
EOF
return 1
}
dangerous_command_check() {
local cmd="$1"
case "$cmd" in
*"rm -rf /"*|*"mkfs"*|*"shutdown"*|*"reboot"*|*"poweroff"*|*"dd if="*)
return 1
;;
esac
local cmd="$1" cwd="${2:-$REMOTE_ROOT}"
contains_dangerous_system_command "$cmd" && return 1
contains_dangerous_rm "$cmd" "$cwd" && return 1
return 0
}
@@ -659,7 +800,11 @@ cmd_exec() {
local_script="$(local_join "$script")"
tmp_name="$(date +%Y%m%d-%H%M%S)-$(basename "$script" | sed 's/[^A-Za-z0-9_.-]/-/g')"
remote_script="$REMOTE_ROOT/.autodl-remote/tmp/$tmp_name"
upload_local_file "$local_script" "$remote_script"
if [ "$ACCOUNT_AUTH" = "keychain" ]; then
upload_local_file "$local_script" "$remote_script" || return 1
else
upload_file_via_ssh "$local_script" "$remote_script" || return 1
fi
if [ $# -gt 0 ]; then
cmd="$* $(shell_quote "$remote_script")"
else
@@ -667,13 +812,17 @@ cmd_exec() {
fi
elif [ "$stdin_mode" = "true" ]; then
[ $# -gt 0 ] || die "exec --stdin requires a command after --, for example: exec --stdin -- bash"
local tmp_local
tmp_local="$(mktemp "${TMPDIR:-/tmp}/autodl-remote-stdin.XXXXXX")" || die "mktemp failed"
cat > "$tmp_local"
tmp_name="$(date +%Y%m%d-%H%M%S)-stdin.sh"
remote_script="$REMOTE_ROOT/.autodl-remote/tmp/$tmp_name"
upload_local_file "$tmp_local" "$remote_script"
rm -f "$tmp_local"
if [ "$ACCOUNT_AUTH" = "keychain" ]; then
local tmp_local
tmp_local="$(mktemp "${TMPDIR:-/tmp}/autodl-remote-stdin.XXXXXX")" || die "mktemp failed"
cat > "$tmp_local"
upload_local_file "$tmp_local" "$remote_script" || { rm -f "$tmp_local"; return 1; }
rm -f "$tmp_local"
else
upload_stdin_to_remote "$remote_script" || return 1
fi
cmd="$* < $(shell_quote "$remote_script")"
else
[ $# -gt 0 ] || die "exec requires a command"
@@ -681,7 +830,7 @@ cmd_exec() {
fi
if [ "$allow_dangerous" != "true" ]; then
dangerous_command_check "$cmd" || die "Dangerous remote command blocked. Re-run with --allow-dangerous after explicit approval."
dangerous_command_check "$cmd" "$cwd" || die "Dangerous remote command blocked. Re-run with --allow-dangerous after explicit approval."
fi
[ -n "$name" ] || name="exec-$(date +%Y%m%d-%H%M%S)"
name="$(sanitize_name "$name")"
@@ -739,13 +888,11 @@ cmd_put() {
fi
else
[ "$dry_run" != "true" ] || die "dry-run requires rsync."
ssh_common_args
local scp_args=(-P "$ACCOUNT_PORT")
[ -n "$ACCOUNT_KEY" ] && scp_args+=(-i "$ACCOUNT_KEY")
scp_common_args
if [ -d "$local_path" ]; then
run_transport scp -r "${scp_args[@]}" "$local_path" "$ACCOUNT_TARGET:$remote_path"
run_transport scp -r "${SCP_ARGS[@]}" "$local_path" "$ACCOUNT_TARGET:$remote_path"
else
run_transport scp "${scp_args[@]}" "$local_path" "$ACCOUNT_TARGET:$remote_path"
run_transport scp "${SCP_ARGS[@]}" "$local_path" "$ACCOUNT_TARGET:$remote_path"
fi
fi
write_history put "$local_arg -> $remote_path"
@@ -785,12 +932,11 @@ cmd_get() {
fi
else
[ "$dry_run" != "true" ] || die "dry-run requires rsync."
local scp_args=(-P "$ACCOUNT_PORT")
[ -n "$ACCOUNT_KEY" ] && scp_args+=(-i "$ACCOUNT_KEY")
scp_common_args
if [ "$kind" = "dir" ]; then
run_transport scp -r "${scp_args[@]}" "$ACCOUNT_TARGET:$remote_path" "$local_path"
run_transport scp -r "${SCP_ARGS[@]}" "$ACCOUNT_TARGET:$remote_path" "$local_path"
else
run_transport scp "${scp_args[@]}" "$ACCOUNT_TARGET:$remote_path" "$local_path"
run_transport scp "${SCP_ARGS[@]}" "$ACCOUNT_TARGET:$remote_path" "$local_path"
fi
fi
write_history get "$remote_path -> $local_arg"