Baca dan konfirmasi skrip shell sebelum melakukan piping dari curl ke sh (curl -s [url] | sh)

11

Setiap kali saya harus menjalankan skrip shell dari web curl -s [url] | sh, saya pertama kali membuka urldi browser web saya untuk memastikan skrip tidak berbahaya dan aman untuk dijalankan.

Saya ingat melihat trik baris perintah yang memungkinkan untuk membaca skrip dari baris perintah dan kemudian mengkonfirmasi eksekusi setelah membaca skrip. Jika saya ingat dengan benar, itu terlihat seperti curl -s [url] | something...here | shdan tidak memerlukan instalasi perangkat lunak.

Adakah yang tahu trik ini?

Olivier Lalonde
sumber

Jawaban:

5

Ada utilitas yang moreutilsdisebut vipestdin yang ditampilkan dalam editor, di mana Anda dapat memperbarui dan memodifikasi file sebelum diteruskan ke stdout.

Jika Anda tidak ingin menginstal moreutils, Anda dapat melakukan hal serupa seperti:

file=$(mktemp); curl -s "$url" > $file; $EDITOR $file; sh $file; rm $file

mktempsedang coreutilsdan sangat mungkin sudah diinstal pada sistem Anda.

Shawn J. Goff
sumber
2

Saya tidak bisa memikirkan satu utilitas yang akan melakukan apa yang Anda gambarkan, tetapi cukup mudah untuk membuat potongan shell.

script=$(curl -s "$url")
printf "%s\nDo you want to run this script? [yN]" "$script"
read line
case $line in
  [Yy]|[Yy][Ee][Ss]) sh -c "$script";;
esac

Ini mengasumsikan skrip adalah file teks. Null byte tidak didukung: tergantung pada shell, mereka dapat dihapus, atau mereka dapat menyebabkan garis atau seluruh file terpotong. Juga semua baris baru di akhir file dihapus (konstruk heredoc menambahkan satu kembali). Biasanya ini bukan masalah untuk skrip, tetapi bisa juga, misalnya, jika skrip berakhir dengan arsip dalam format biner yang diekstraksi. Ini bukan cara yang sangat andal dalam mendistribusikan file karena ada risiko yang signifikan dari skrip biner seperti itu untuk salah kode pada beberapa titik. Meskipun demikian, Anda dapat menanganinya dengan menulis skrip ke file sementara.

script_file=$(mktemp)
curl -s "$url" | tee "$script_file"
printf "Do you want to run this script? [yN]"
read line
case $line in
  [Yy]|[Yy][Ee][Ss]) sh "$script_file";;
esac
rm "$script_file"
Gilles 'SANGAT berhenti menjadi jahat'
sumber
$()harus dikutip di baris pertama. Juga, ini akan menghapus karakter NUL dalam input, yang mungkin berakibat fatal (misalnya dalam kasus skrip self-extracting).
l0b0
1
@ l0b0 Anda tidak perlu mengutip dalam suatu tugas, meskipun itu gaya yang bisa dibilang bagus . Null byte memang hilang, seperti juga baris baru akhir; jika Anda akan memasukkan arsip dalam skrip shell, saya sarankan menggunakan pengkodean teks seperti base64.
Gilles 'SO- stop being evil'
Semua poin valid, seperti biasa. +1
l0b0
@ l0b0 Pada pikiran kedua, meskipun agak rawan risiko, ini adalah kasus penggunaan yang valid. Saya telah memperbarui jawaban saya. Saya juga mengoreksi cacat pada jawaban asli saya yang tidak memungkinkan skrip untuk menggunakan stdin-nya (karena skrip diteruskan pada stdin, tanpa alasan yang baik).
Gilles 'SANGAT berhenti menjadi jahat'
1

Sulit membayangkan mengapa Anda bahkan ingin melakukan ini, apalagi di mana Anda akan menemukan sumber (atau sumber) skrip untuk diunduh dan dijalankan seperti ini cukup sering sehingga memerlukan alat tujuan khusus.

Mengapa tidak mengunduh skrip dengan curl(atau wgetatau snarfapa pun), memeriksa dan mengeditnya (skrip langka yang tidak memerlukan penyesuaian untuk sistem khusus Anda) dan kemudian menjalankannya - baik dengan membuatnya dapat dieksekusi dengan chmodatau dengan sh scriptname?

cas
sumber
Saya tidak ingin alat tujuan khusus. Saya ingat ada cara mudah untuk melakukan ini dengan alat standar.
Olivier Lalonde
2
Tidak akan sulit untuk menulis skrip shell kecil (mungkin hanya 5 atau lebih baris) untuk mengunduh skrip, menyajikannya untuk dilihat bersama lessatau sesuatu, dan kemudian bertanya kepada Anda apakah Anda ingin menjalankannya. Saya tidak dapat melihat bahwa itu akan lebih baik daripada hanya mengunduh skrip, melihatnya, dan kemudian menjalankannya jika tampaknya OK. IMO itu akan lebih buruk, itu tidak akan menawarkan keuntungan apa pun tetapi akan menghapus fleksibilitas yang Anda dapatkan dari hanya bekerja di shell Anda.
cas
0

Gunakan baris perintah ini:

curl URL | ( cat > /tmp/file; read REPLY; [[ ! $REPLY =~ ^[Yy]$ ]] && cat /tmp/file ) | sh

Anda dapat menggunakan fungsi kecil untuk itu:

curlsh()
{
    curl "$1" \
    | ( cat > /tmp/file;read REPLY; [[ ! $REPLY =~ ^[Yy]$ ]] && cat /tmp/file ) \
    | sh
}

Dan daripada menggunakannya dengan cara ini:

curlsh http://site.in.net/path/to/script
Igor Chubin
sumber
0

Dengan asumsi read know -p (prompt) Anda, dan skrip tidak perlu dijalankan dengan interpreter, ditentukan oleh shebang:

curl URL | tee /tmp/x && read -p "execute?" key ; test $key = y && sh /tmp/x
Pengguna tidak diketahui
sumber