From 459d2f886b9c4a7a95fce6e3336d40f114b0c48f Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Sat, 16 May 2026 14:38:56 +0800 Subject: [PATCH 1/2] chore(deps): upgrade third-party dependencies - Upgrade golang.org/x/crypto to v0.51.0 - Upgrade golang.org/x/sys to v0.44.0 - Bump examples to easyssh-proxy v1.5.2 --- _examples/proxy/go.mod | 6 +++--- _examples/proxy/go.sum | 14 ++++++++------ _examples/scp/go.mod | 6 +++--- _examples/scp/go.sum | 14 ++++++++------ _examples/ssh/go.mod | 6 +++--- _examples/ssh/go.sum | 14 ++++++++------ _examples/stream/go.mod | 6 +++--- _examples/stream/go.sum | 14 ++++++++------ _examples/writeFile/go.mod | 6 +++--- _examples/writeFile/go.sum | 14 ++++++++------ go.mod | 4 ++-- go.sum | 12 ++++++------ 12 files changed, 63 insertions(+), 53 deletions(-) diff --git a/_examples/proxy/go.mod b/_examples/proxy/go.mod index ef1903f..497ea64 100644 --- a/_examples/proxy/go.mod +++ b/_examples/proxy/go.mod @@ -2,13 +2,13 @@ module example go 1.25.10 -require github.com/appleboy/easyssh-proxy v1.5.0 +require github.com/appleboy/easyssh-proxy v1.5.2 require ( github.com/ScaleFT/sshkeys v1.4.0 // indirect github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect - golang.org/x/crypto v0.43.0 // indirect - golang.org/x/sys v0.37.0 // indirect + golang.org/x/crypto v0.51.0 // indirect + golang.org/x/sys v0.44.0 // indirect ) replace github.com/appleboy/easyssh-proxy v1.5.0 => ../../ diff --git a/_examples/proxy/go.sum b/_examples/proxy/go.sum index 9b3c339..d224e02 100644 --- a/_examples/proxy/go.sum +++ b/_examples/proxy/go.sum @@ -1,5 +1,7 @@ github.com/ScaleFT/sshkeys v1.4.0 h1:Yqd0cKA5PUvwV0dgRI67BDHGTsMHtGQBZbLXh1dthmE= github.com/ScaleFT/sshkeys v1.4.0/go.mod h1:GineMkS8SEiELq8q5DzA2Wnrw65SqdD9a+hm8JOU1I4= +github.com/appleboy/easyssh-proxy v1.5.2 h1:Fe4/RMNtoU/l36w5DvOEyMX3VcpwUbqZYBdPugqODOs= +github.com/appleboy/easyssh-proxy v1.5.2/go.mod h1:cv8OlpCbAdxVNYgY/vQcM7f/Ep51UG5oyLK+J2kZhEc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a h1:saTgr5tMLFnmy/yg3qDTft4rE5DY2uJ/cCxCe3q0XTU= @@ -8,11 +10,11 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/_examples/scp/go.mod b/_examples/scp/go.mod index ef1903f..497ea64 100644 --- a/_examples/scp/go.mod +++ b/_examples/scp/go.mod @@ -2,13 +2,13 @@ module example go 1.25.10 -require github.com/appleboy/easyssh-proxy v1.5.0 +require github.com/appleboy/easyssh-proxy v1.5.2 require ( github.com/ScaleFT/sshkeys v1.4.0 // indirect github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect - golang.org/x/crypto v0.43.0 // indirect - golang.org/x/sys v0.37.0 // indirect + golang.org/x/crypto v0.51.0 // indirect + golang.org/x/sys v0.44.0 // indirect ) replace github.com/appleboy/easyssh-proxy v1.5.0 => ../../ diff --git a/_examples/scp/go.sum b/_examples/scp/go.sum index 9b3c339..d224e02 100644 --- a/_examples/scp/go.sum +++ b/_examples/scp/go.sum @@ -1,5 +1,7 @@ github.com/ScaleFT/sshkeys v1.4.0 h1:Yqd0cKA5PUvwV0dgRI67BDHGTsMHtGQBZbLXh1dthmE= github.com/ScaleFT/sshkeys v1.4.0/go.mod h1:GineMkS8SEiELq8q5DzA2Wnrw65SqdD9a+hm8JOU1I4= +github.com/appleboy/easyssh-proxy v1.5.2 h1:Fe4/RMNtoU/l36w5DvOEyMX3VcpwUbqZYBdPugqODOs= +github.com/appleboy/easyssh-proxy v1.5.2/go.mod h1:cv8OlpCbAdxVNYgY/vQcM7f/Ep51UG5oyLK+J2kZhEc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a h1:saTgr5tMLFnmy/yg3qDTft4rE5DY2uJ/cCxCe3q0XTU= @@ -8,11 +10,11 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/_examples/ssh/go.mod b/_examples/ssh/go.mod index ef1903f..497ea64 100644 --- a/_examples/ssh/go.mod +++ b/_examples/ssh/go.mod @@ -2,13 +2,13 @@ module example go 1.25.10 -require github.com/appleboy/easyssh-proxy v1.5.0 +require github.com/appleboy/easyssh-proxy v1.5.2 require ( github.com/ScaleFT/sshkeys v1.4.0 // indirect github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect - golang.org/x/crypto v0.43.0 // indirect - golang.org/x/sys v0.37.0 // indirect + golang.org/x/crypto v0.51.0 // indirect + golang.org/x/sys v0.44.0 // indirect ) replace github.com/appleboy/easyssh-proxy v1.5.0 => ../../ diff --git a/_examples/ssh/go.sum b/_examples/ssh/go.sum index 9b3c339..d224e02 100644 --- a/_examples/ssh/go.sum +++ b/_examples/ssh/go.sum @@ -1,5 +1,7 @@ github.com/ScaleFT/sshkeys v1.4.0 h1:Yqd0cKA5PUvwV0dgRI67BDHGTsMHtGQBZbLXh1dthmE= github.com/ScaleFT/sshkeys v1.4.0/go.mod h1:GineMkS8SEiELq8q5DzA2Wnrw65SqdD9a+hm8JOU1I4= +github.com/appleboy/easyssh-proxy v1.5.2 h1:Fe4/RMNtoU/l36w5DvOEyMX3VcpwUbqZYBdPugqODOs= +github.com/appleboy/easyssh-proxy v1.5.2/go.mod h1:cv8OlpCbAdxVNYgY/vQcM7f/Ep51UG5oyLK+J2kZhEc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a h1:saTgr5tMLFnmy/yg3qDTft4rE5DY2uJ/cCxCe3q0XTU= @@ -8,11 +10,11 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/_examples/stream/go.mod b/_examples/stream/go.mod index ef1903f..497ea64 100644 --- a/_examples/stream/go.mod +++ b/_examples/stream/go.mod @@ -2,13 +2,13 @@ module example go 1.25.10 -require github.com/appleboy/easyssh-proxy v1.5.0 +require github.com/appleboy/easyssh-proxy v1.5.2 require ( github.com/ScaleFT/sshkeys v1.4.0 // indirect github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect - golang.org/x/crypto v0.43.0 // indirect - golang.org/x/sys v0.37.0 // indirect + golang.org/x/crypto v0.51.0 // indirect + golang.org/x/sys v0.44.0 // indirect ) replace github.com/appleboy/easyssh-proxy v1.5.0 => ../../ diff --git a/_examples/stream/go.sum b/_examples/stream/go.sum index 9b3c339..d224e02 100644 --- a/_examples/stream/go.sum +++ b/_examples/stream/go.sum @@ -1,5 +1,7 @@ github.com/ScaleFT/sshkeys v1.4.0 h1:Yqd0cKA5PUvwV0dgRI67BDHGTsMHtGQBZbLXh1dthmE= github.com/ScaleFT/sshkeys v1.4.0/go.mod h1:GineMkS8SEiELq8q5DzA2Wnrw65SqdD9a+hm8JOU1I4= +github.com/appleboy/easyssh-proxy v1.5.2 h1:Fe4/RMNtoU/l36w5DvOEyMX3VcpwUbqZYBdPugqODOs= +github.com/appleboy/easyssh-proxy v1.5.2/go.mod h1:cv8OlpCbAdxVNYgY/vQcM7f/Ep51UG5oyLK+J2kZhEc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a h1:saTgr5tMLFnmy/yg3qDTft4rE5DY2uJ/cCxCe3q0XTU= @@ -8,11 +10,11 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/_examples/writeFile/go.mod b/_examples/writeFile/go.mod index ef1903f..497ea64 100644 --- a/_examples/writeFile/go.mod +++ b/_examples/writeFile/go.mod @@ -2,13 +2,13 @@ module example go 1.25.10 -require github.com/appleboy/easyssh-proxy v1.5.0 +require github.com/appleboy/easyssh-proxy v1.5.2 require ( github.com/ScaleFT/sshkeys v1.4.0 // indirect github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect - golang.org/x/crypto v0.43.0 // indirect - golang.org/x/sys v0.37.0 // indirect + golang.org/x/crypto v0.51.0 // indirect + golang.org/x/sys v0.44.0 // indirect ) replace github.com/appleboy/easyssh-proxy v1.5.0 => ../../ diff --git a/_examples/writeFile/go.sum b/_examples/writeFile/go.sum index 9b3c339..d224e02 100644 --- a/_examples/writeFile/go.sum +++ b/_examples/writeFile/go.sum @@ -1,5 +1,7 @@ github.com/ScaleFT/sshkeys v1.4.0 h1:Yqd0cKA5PUvwV0dgRI67BDHGTsMHtGQBZbLXh1dthmE= github.com/ScaleFT/sshkeys v1.4.0/go.mod h1:GineMkS8SEiELq8q5DzA2Wnrw65SqdD9a+hm8JOU1I4= +github.com/appleboy/easyssh-proxy v1.5.2 h1:Fe4/RMNtoU/l36w5DvOEyMX3VcpwUbqZYBdPugqODOs= +github.com/appleboy/easyssh-proxy v1.5.2/go.mod h1:cv8OlpCbAdxVNYgY/vQcM7f/Ep51UG5oyLK+J2kZhEc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a h1:saTgr5tMLFnmy/yg3qDTft4rE5DY2uJ/cCxCe3q0XTU= @@ -8,11 +10,11 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/go.mod b/go.mod index 363aabb..fcd68a4 100644 --- a/go.mod +++ b/go.mod @@ -5,13 +5,13 @@ go 1.25.10 require ( github.com/ScaleFT/sshkeys v1.4.0 github.com/stretchr/testify v1.8.4 - golang.org/x/crypto v0.43.0 + golang.org/x/crypto v0.51.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.37.0 // indirect + golang.org/x/sys v0.44.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 919fabb..bebb674 100644 --- a/go.sum +++ b/go.sum @@ -8,12 +8,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= From 14141ba644fdccb7f9c00f14676d423c259b4848 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Sun, 17 May 2026 13:01:17 +0800 Subject: [PATCH 2/2] fix: harden SCP path and patch several leaks - Reject SCP target paths with shell or SCP-protocol metacharacters to prevent remote command injection - Close the proxyClient SSH connection when its target client closes or times out - Fix sshAgent socket leak caused by variable shadowing in getSSHConfig - Resolve data race on the shared err variable in Stream reader goroutines - Break Stream readers on any read error so client.Close unblocks them on timeout - Add ErrFingerprintMismatch and ErrInvalidTargetFile sentinel errors - Cover the new shellQuote helper and WriteFile validation with unit tests --- easyssh.go | 143 +++++++++++++++++++++++++----------------------- easyssh_test.go | 43 +++++++++++++++ 2 files changed, 118 insertions(+), 68 deletions(-) diff --git a/easyssh.go b/easyssh.go index 7bdfd68..f8a1f2c 100644 --- a/easyssh.go +++ b/easyssh.go @@ -23,7 +23,7 @@ import ( "golang.org/x/crypto/ssh/agent" ) -var ( +const ( defaultTimeout = 60 * time.Second defaultBufferSize = 4096 ) @@ -31,6 +31,11 @@ var ( var ( // ErrProxyDialTimeout is returned when proxy dial connection times out ErrProxyDialTimeout = errors.New("proxy dial timeout") + // ErrFingerprintMismatch is returned when the remote host key fingerprint does not match the configured one. + ErrFingerprintMismatch = errors.New("ssh: host key fingerprint mismatch") + // ErrInvalidTargetFile is returned when an SCP target filename contains characters + // that would corrupt the SCP control stream (newline, carriage return, or NUL). + ErrInvalidTargetFile = errors.New("easyssh: invalid characters in target filename") ) type Protocol string @@ -168,8 +173,9 @@ func getSSHConfig(config DefaultConfig) (*ssh.ClientConfig, io.Closer) { } } - if sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil { - auths = append(auths, ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)) + if sock, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil { + sshAgent = sock + auths = append(auths, ssh.PublicKeysCallback(agent.NewClient(sock).Signers)) } c := ssh.Config{} @@ -191,7 +197,7 @@ func getSSHConfig(config DefaultConfig) (*ssh.ClientConfig, io.Closer) { if config.Fingerprint != "" { hostKeyCallback = func(hostname string, remote net.Addr, publicKey ssh.PublicKey) error { if ssh.FingerprintSHA256(publicKey) != config.Fingerprint { - return fmt.Errorf("ssh: host key fingerprint mismatch") + return ErrFingerprintMismatch } return nil } @@ -292,19 +298,27 @@ func (ssh_conf *MakeConfig) Connect() (*ssh.Session, *ssh.Client, error) { conn = result.conn err = result.err case <-ctx.Done(): + _ = proxyClient.Close() return nil, nil, fmt.Errorf("%w: %v", ErrProxyDialTimeout, ctx.Err()) } if err != nil { + _ = proxyClient.Close() return nil, nil, err } ncc, chans, reqs, err := ssh.NewClientConn(conn, net.JoinHostPort(ssh_conf.Server, ssh_conf.Port), targetConfig) if err != nil { + _ = proxyClient.Close() return nil, nil, err } client = ssh.NewClient(ncc, chans, reqs) + // Close the proxy client once the target client is closed by the caller. + go func() { + _ = client.Wait() + _ = proxyClient.Close() + }() } else { client, err = ssh.Dial(string(ssh_conf.Protocol), net.JoinHostPort(ssh_conf.Server, ssh_conf.Port), targetConfig) if err != nil { @@ -343,97 +357,76 @@ func (ssh_conf *MakeConfig) Stream(command string, timeout ...time.Duration) (<- doneChan := make(chan bool) errChan := make(chan error) - // connect to remote host session, client, err := ssh_conf.Connect() if err != nil { return stdoutChan, stderrChan, doneChan, errChan, err } - // defer session.Close() - // connect to both outputs (they are of type io.Reader) + + closeBoth := func() { + _ = session.Close() + _ = client.Close() + } + outReader, err := session.StdoutPipe() if err != nil { - _ = client.Close() - _ = session.Close() + closeBoth() return stdoutChan, stderrChan, doneChan, errChan, err } errReader, err := session.StderrPipe() if err != nil { - _ = client.Close() - _ = session.Close() + closeBoth() return stdoutChan, stderrChan, doneChan, errChan, err } - err = session.Start(command) - if err != nil { - _ = client.Close() - _ = session.Close() + if err = session.Start(command); err != nil { + closeBoth() return stdoutChan, stderrChan, doneChan, errChan, err } - // combine outputs, create a line-by-line scanner - stdoutReader := io.MultiReader(outReader) - stderrReader := io.MultiReader(errReader) - - var stdoutScanner *bufio.Reader - var stderrScanner *bufio.Reader - - if ssh_conf.ReadBuffSize > 0 { - stdoutScanner = bufio.NewReaderSize(stdoutReader, ssh_conf.ReadBuffSize) - } else { - stdoutScanner = bufio.NewReaderSize(stdoutReader, defaultBufferSize) + bufSize := ssh_conf.ReadBuffSize + if bufSize <= 0 { + bufSize = defaultBufferSize } + stdoutScanner := bufio.NewReaderSize(outReader, bufSize) + stderrScanner := bufio.NewReaderSize(errReader, bufSize) - if ssh_conf.ReadBuffSize > 0 { - stderrScanner = bufio.NewReaderSize(stderrReader, ssh_conf.ReadBuffSize) - } else { - stderrScanner = bufio.NewReaderSize(stderrReader, defaultBufferSize) + executeTimeout := defaultTimeout + if len(timeout) > 0 { + executeTimeout = timeout[0] } - go func(stdoutScanner, stderrScanner *bufio.Reader, stdoutChan, stderrChan chan string, doneChan chan bool, errChan chan error) { + go func() { defer close(doneChan) defer close(errChan) - defer func() { _ = client.Close() }() - defer func() { _ = session.Close() }() + defer closeBoth() - // default timeout value - executeTimeout := defaultTimeout - if len(timeout) > 0 { - executeTimeout = timeout[0] - } ctxTimeout, cancel := context.WithTimeout(context.Background(), executeTimeout) defer cancel() - res := make(chan struct{}, 1) - var resWg sync.WaitGroup - resWg.Add(2) - go func() { - defer close(stdoutChan) + scan := func(r *bufio.Reader, out chan<- string) { + defer close(out) for { - var text string - text, err = stdoutScanner.ReadString('\n') - if errors.Is(err, io.EOF) { - break + text, readErr := r.ReadString('\n') + if text != "" { + select { + case out <- strings.TrimRight(text, "\n"): + case <-ctxTimeout.Done(): + return + } } - stdoutChan <- strings.TrimRight(text, "\n") - } - resWg.Done() - }() - - go func() { - defer close(stderrChan) - for { - var text string - text, err = stderrScanner.ReadString('\n') - if errors.Is(err, io.EOF) { - break + if readErr != nil { + return } - stderrChan <- strings.TrimRight(text, "\n") } - resWg.Done() - }() + } + + var resWg sync.WaitGroup + resWg.Add(2) + go func() { defer resWg.Done(); scan(stdoutScanner, stdoutChan) }() + go func() { defer resWg.Done(); scan(stderrScanner, stderrChan) }() + res := make(chan struct{}, 1) go func() { resWg.Wait() - // close all of our open resources res <- struct{}{} }() @@ -442,10 +435,10 @@ func (ssh_conf *MakeConfig) Stream(command string, timeout ...time.Duration) (<- errChan <- session.Wait() doneChan <- true case <-ctxTimeout.Done(): - errChan <- fmt.Errorf("Run Command Timeout: %v", ctxTimeout.Err()) + errChan <- fmt.Errorf("Run Command Timeout: %w", ctxTimeout.Err()) doneChan <- false } - }(stdoutScanner, stderrScanner, stdoutChan, stderrChan, doneChan, errChan) + }() return stdoutChan, stderrChan, doneChan, errChan, err } @@ -489,6 +482,15 @@ loop: // WriteFile reads size bytes from the reader and writes them to a file on the remote machine func (ssh_conf *MakeConfig) WriteFile(reader io.Reader, size int64, etargetFile string) error { + targetFile := filepath.Base(etargetFile) + // Reject characters that would either inject extra SCP control records + // (\n, \r) or terminate the filename field early (\x00). The remote-side + // scp command is invoked through the user's shell, so etargetFile is + // single-quoted below to neutralise shell metacharacters. + if strings.ContainsAny(etargetFile, "\x00\n\r") || strings.ContainsAny(targetFile, "\x00\n\r") { + return ErrInvalidTargetFile + } + session, client, err := ssh_conf.Connect() if err != nil { return err @@ -496,8 +498,6 @@ func (ssh_conf *MakeConfig) WriteFile(reader io.Reader, size int64, etargetFile defer func() { _ = client.Close() }() defer func() { _ = session.Close() }() - targetFile := filepath.Base(etargetFile) - w, err := session.StdinPipe() if err != nil { return err @@ -530,7 +530,7 @@ func (ssh_conf *MakeConfig) WriteFile(reader io.Reader, size int64, etargetFile copyErrC <- copyF() }() - err = session.Run(fmt.Sprintf("scp -tr %s", etargetFile)) + err = session.Run("scp -tr " + shellQuote(etargetFile)) if err != nil { return err } @@ -539,6 +539,13 @@ func (ssh_conf *MakeConfig) WriteFile(reader io.Reader, size int64, etargetFile return err } +// shellQuote returns s wrapped in POSIX single quotes so it can be passed as +// one shell word. Embedded single quotes are escaped using the +// close-quote/backslash-quote/open-quote idiom. +func shellQuote(s string) string { + return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'" +} + // Scp uploads sourceFile to remote machine like native scp console app. func (ssh_conf *MakeConfig) Scp(sourceFile string, etargetFile string) error { session, client, err := ssh_conf.Connect() diff --git a/easyssh_test.go b/easyssh_test.go index ec3edeb..5f87ead 100644 --- a/easyssh_test.go +++ b/easyssh_test.go @@ -1,6 +1,7 @@ package easyssh import ( + "bytes" "context" "errors" "os" @@ -666,3 +667,45 @@ func TestProxyGoroutineLeak(t *testing.T) { "Goroutine leak detected: initial=%d, final=%d", initialGoroutines, finalGoroutines) } +// TestShellQuote pins the contract of the helper used to defend the SCP code +// path against remote command injection. If any of these cases regress, an +// attacker-controlled target path could execute arbitrary commands on the +// remote host. +func TestShellQuote(t *testing.T) { + cases := []struct { + in, want string + }{ + {"", "''"}, + {"foo", "'foo'"}, + {"foo bar", "'foo bar'"}, + {"foo/bar.txt", "'foo/bar.txt'"}, + {"foo'bar", `'foo'\''bar'`}, + {"'", `''\'''`}, + {"$(rm -rf /)", "'$(rm -rf /)'"}, + {"`id`", "'`id`'"}, + {"a;b|c&d", "'a;b|c&d'"}, + {`"quoted"`, `'"quoted"'`}, + } + for _, c := range cases { + got := shellQuote(c.in) + assert.Equal(t, c.want, got, "shellQuote(%q)", c.in) + } +} + +// TestWriteFileRejectsInvalidTargetName guards the SCP protocol-injection +// fix: a target filename containing newline/CR/NUL must be rejected before +// any network I/O, so a malicious caller cannot smuggle extra SCP control +// records (e.g. a second "C0755 ... /etc/shadow" line) into the stream. +func TestWriteFileRejectsInvalidTargetName(t *testing.T) { + ssh := &MakeConfig{Server: "127.0.0.1", User: "nobody", Port: "22"} + for _, bad := range []string{ + "foo\nbar", + "foo\rbar", + "foo\x00bar", + "dir/with\nnewline", + } { + err := ssh.WriteFile(bytes.NewReader(nil), 0, bad) + assert.ErrorIs(t, err, ErrInvalidTargetFile, "WriteFile(%q) should reject", bad) + } +} +