diff --git a/agent/app/api/v2/file.go b/agent/app/api/v2/file.go
index 6d4173197..22b892c2f 100644
--- a/agent/app/api/v2/file.go
+++ b/agent/app/api/v2/file.go
@@ -640,6 +640,10 @@ func (b *BaseApi) MoveFile(c *gin.Context) {
// @Router /files/download [get]
func (b *BaseApi) Download(c *gin.Context) {
filePath := c.Query("path")
+ if files.ShouldDenySensitiveFileRead(filePath) {
+ helper.InternalServer(c, buserr.New("ErrSensitiveFileRead"))
+ return
+ }
file, err := os.Open(filePath)
if err != nil {
helper.InternalServer(c, err)
@@ -675,6 +679,10 @@ func (b *BaseApi) DownloadChunkFiles(c *gin.Context) {
helper.ErrorWithDetail(c, http.StatusInternalServerError, "ErrPathNotFound", nil)
return
}
+ if files.ShouldDenySensitiveFileRead(req.Path) {
+ helper.InternalServer(c, buserr.New("ErrSensitiveFileRead"))
+ return
+ }
filePath := req.Path
fstFile, err := fileOp.OpenFile(filePath)
if err != nil {
@@ -1335,6 +1343,10 @@ func (b *BaseApi) DownloadFileShare(c *gin.Context) {
helper.InternalServer(c, err)
return
}
+ if files.ShouldDenySensitiveFileRead(filePath) {
+ helper.InternalServer(c, buserr.New("ErrSensitiveFileRead"))
+ return
+ }
file, err := os.Open(filePath)
if err != nil {
helper.InternalServer(c, err)
diff --git a/agent/app/service/file.go b/agent/app/service/file.go
index d8dc8b2e7..d376b54e4 100644
--- a/agent/app/service/file.go
+++ b/agent/app/service/file.go
@@ -669,6 +669,9 @@ func applyDecompressOwnership(srcPath, dstPath string) error {
}
func (f *FileService) GetContent(op request.FileContentReq) (response.FileInfo, error) {
+ if files.ShouldDenySensitiveFileRead(op.Path) {
+ return response.FileInfo{}, buserr.New("ErrSensitiveFileRead")
+ }
info, err := files.NewFileInfo(files.FileOption{
Path: op.Path,
Expand: true,
@@ -705,6 +708,9 @@ func (f *FileService) GetContent(op request.FileContentReq) (response.FileInfo,
}
func (f *FileService) GetPreviewContent(op request.FileContentReq) (response.FileInfo, error) {
+ if files.ShouldDenySensitiveFileRead(op.Path) {
+ return response.FileInfo{}, buserr.New("ErrSensitiveFileRead")
+ }
info, err := files.NewFileInfo(files.FileOption{
Path: op.Path,
Expand: false,
@@ -945,6 +951,11 @@ func buildHistoryMoveTargetPath(dst, name, sourcePath string, sourceCount int) s
}
func (f *FileService) FileDownload(d request.FileDownload) (string, error) {
+ for _, p := range d.Paths {
+ if files.ShouldDenySensitiveFileRead(p) {
+ return "", buserr.New("ErrSensitiveFileRead")
+ }
+ }
filePath := d.Paths[0]
if d.Compress {
tempPath := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().UnixNano()))
diff --git a/agent/app/service/file_share.go b/agent/app/service/file_share.go
index 9718e712c..8b0ed91ad 100644
--- a/agent/app/service/file_share.go
+++ b/agent/app/service/file_share.go
@@ -20,6 +20,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
+ "github.com/1Panel-dev/1Panel/agent/utils/files"
"gorm.io/gorm"
)
@@ -131,6 +132,9 @@ func (s *FileShareService) Create(req request.FileShareCreate) (*response.FileSh
if path == "" || strings.Contains(path, "..") {
return nil, buserr.New("ErrFileSharePath")
}
+ if files.ShouldDenySensitiveFileRead(path) {
+ return nil, buserr.New("ErrSensitiveFileRead")
+ }
info, err := os.Stat(path)
if err != nil || info.IsDir() {
return nil, buserr.New("ErrFileSharePath")
diff --git a/agent/i18n/lang/en.yaml b/agent/i18n/lang/en.yaml
index 045bfc2ef..910e97a2b 100644
--- a/agent/i18n/lang/en.yaml
+++ b/agent/i18n/lang/en.yaml
@@ -139,6 +139,7 @@ ExportDate: "Time"
#file
ErrFileCanNotRead: 'File preview is not supported'
+ErrSensitiveFileRead: 'Reading sensitive files is not allowed'
ErrFileToLarge: 'File is larger than 10 MB'
ErrPathNotFound: 'Directory does not exist'
ErrMovePathFailed: 'Target path cannot include source path'
diff --git a/agent/i18n/lang/es-ES.yaml b/agent/i18n/lang/es-ES.yaml
index 5f674ac5f..c93803e5b 100644
--- a/agent/i18n/lang/es-ES.yaml
+++ b/agent/i18n/lang/es-ES.yaml
@@ -134,6 +134,7 @@ ExportUser: 'Usuario'
ExportStatus: 'Estado de inicio de sesión'
ExportDate: 'Fecha y hora'
ErrFileCanNotRead: 'Este archivo no soporta vista previa'
+ErrSensitiveFileRead: 'No se permite leer archivos sensibles'
ErrFileToLarge: 'El archivo es mayor a 10M y no puede abrirse'
ErrPathNotFound: 'El directorio no existe'
ErrMovePathFailed: 'La ruta de destino no puede contener la ruta original'
diff --git a/agent/i18n/lang/ja.yaml b/agent/i18n/lang/ja.yaml
index 0e4b46d2f..8fffc9c46 100644
--- a/agent/i18n/lang/ja.yaml
+++ b/agent/i18n/lang/ja.yaml
@@ -134,6 +134,7 @@ ExportUser: 'ユーザー'
ExportStatus: 'ログイン状態'
ExportDate: '時間'
ErrFileCanNotRead: 'このファイルはプレビューをサポートしていません'
+ErrSensitiveFileRead: '機密ファイルの読み取りは許可されていません'
ErrFileToLarge: 'ファイルは 10M より大きいため開けません'
ErrPathNotFound: 'ディレクトリが存在しません'
ErrMovePathFailed: 'ターゲット パスに元のパスを含めることはできません'
diff --git a/agent/i18n/lang/ko.yaml b/agent/i18n/lang/ko.yaml
index 0c030a689..fd76983f7 100644
--- a/agent/i18n/lang/ko.yaml
+++ b/agent/i18n/lang/ko.yaml
@@ -134,6 +134,7 @@ ExportUser: '사용자'
ExportStatus: '로그인 상태'
ExportDate: '시간'
ErrFileCanNotRead: '이 파일은 미리보기를 지원하지 않습니다'
+ErrSensitiveFileRead: '민감한 파일을 읽을 수 없습니다'
ErrFileToLarge: '파일이 10M보다 커서 열 수 없습니다'
ErrPathNotFound: '디렉토리가 존재하지 않습니다'
ErrMovePathFailed: '대상 경로에는 원래 경로가 포함될 수 없습니다'
diff --git a/agent/i18n/lang/ms.yaml b/agent/i18n/lang/ms.yaml
index d55bb9d20..3d6f02c58 100644
--- a/agent/i18n/lang/ms.yaml
+++ b/agent/i18n/lang/ms.yaml
@@ -134,6 +134,7 @@ ExportUser: 'Pengguna'
ExportStatus: 'Status Log Masuk'
ExportDate: 'Masa'
ErrFileCanNotRead: 'Fail ini tidak menyokong pratonton'
+ErrSensitiveFileRead: 'Membaca fail sensitif tidak dibenarkan'
ErrFileToLarge: 'Fail lebih besar daripada 10M dan tidak boleh dibuka'
ErrPathNotFound: 'Direktori tidak wujud'
ErrMovePathFailed: 'Laluan sasaran tidak boleh mengandungi laluan asal'
diff --git a/agent/i18n/lang/pt-BR.yaml b/agent/i18n/lang/pt-BR.yaml
index 632854c02..3513d6771 100644
--- a/agent/i18n/lang/pt-BR.yaml
+++ b/agent/i18n/lang/pt-BR.yaml
@@ -134,6 +134,7 @@ ExportUser: 'Usuário'
ExportStatus: 'Status de Login'
ExportDate: 'Hora'
ErrFileCanNotRead: 'Este arquivo não suporta visualização'
+ErrSensitiveFileRead: 'A leitura de arquivos sensíveis não é permitida'
ErrFileToLarge: 'O arquivo é maior que 10M e não pode ser aberto'
ErrPathNotFound: 'O diretório não existe'
ErrMovePathFailed: 'O caminho de destino não pode conter o caminho original'
diff --git a/agent/i18n/lang/ru.yaml b/agent/i18n/lang/ru.yaml
index 76c8deac7..9eae4f9d2 100644
--- a/agent/i18n/lang/ru.yaml
+++ b/agent/i18n/lang/ru.yaml
@@ -134,6 +134,7 @@ ExportUser: 'Пользователь'
ExportStatus: 'Статус входа'
ExportDate: 'Время'
ErrFileCanNotRead: 'Этот файл не поддерживает предварительный просмотр'
+ErrSensitiveFileRead: 'Чтение конфиденциальных файлов запрещено'
ErrFileToLarge: 'Файл больше 10 МБ и не может быть открыт'
ErrPathNotFound: 'Каталог не существует'
ErrMovePathFailed: 'Целевой путь не может содержать исходный путь'
diff --git a/agent/i18n/lang/tr.yaml b/agent/i18n/lang/tr.yaml
index 98c8e4345..a1ee7a240 100644
--- a/agent/i18n/lang/tr.yaml
+++ b/agent/i18n/lang/tr.yaml
@@ -134,6 +134,7 @@ ExportUser: 'Kullanıcı'
ExportStatus: 'Giriş Durumu'
ExportDate: 'Zaman'
ErrFileCanNotRead: 'Bu dosya önizlemeyi desteklemiyor'
+ErrSensitiveFileRead: 'Hassas dosyaların okunmasına izin verilmez'
ErrFileToLarge: 'Dosya 10M dan büyük ve açılamıyor'
ErrPathNotFound: 'Dizin mevcut değil'
ErrMovePathFailed: 'Hedef yol orijinal yolu içeremez'
diff --git a/agent/i18n/lang/zh-Hant.yaml b/agent/i18n/lang/zh-Hant.yaml
index 955af078c..4bdd39239 100644
--- a/agent/i18n/lang/zh-Hant.yaml
+++ b/agent/i18n/lang/zh-Hant.yaml
@@ -134,6 +134,7 @@ ExportUser: '使用者'
ExportStatus: '登入狀態'
ExportDate: '時間'
ErrFileCanNotRead: '此檔案不支援預覽'
+ErrSensitiveFileRead: '不允許讀取敏感檔案'
ErrFileToLarge: '檔案超過10M,無法開啟'
ErrPathNotFound: '目錄不存在'
ErrMovePathFailed: '目標路徑不可包含原路徑!'
diff --git a/agent/i18n/lang/zh.yaml b/agent/i18n/lang/zh.yaml
index bbd3974f9..0b0c89777 100644
--- a/agent/i18n/lang/zh.yaml
+++ b/agent/i18n/lang/zh.yaml
@@ -139,6 +139,7 @@ ExportDate: "时间"
#file
ErrFileCanNotRead: "此文件不支持预览"
+ErrSensitiveFileRead: "不允许读取敏感文件"
ErrFileToLarge: "文件超过 10M,无法打开"
ErrPathNotFound: "目录不存在"
ErrMovePathFailed: "目标路径不能包含原路径!"
diff --git a/agent/utils/files/path_filter.go b/agent/utils/files/path_filter.go
index 39e3ef13e..b9f428522 100644
--- a/agent/utils/files/path_filter.go
+++ b/agent/utils/files/path_filter.go
@@ -17,5 +17,31 @@ func ShouldFilterSensitivePath(path string) bool {
return true
}
}
+ return ShouldDenySensitiveFileRead(path)
+}
+
+func ShouldDenySensitiveFileRead(path string) bool {
+ if isSensitiveSSHPath(path) {
+ return true
+ }
+ realPath, err := filepath.EvalSymlinks(path)
+ if err != nil {
+ return false
+ }
+ return isSensitiveSSHPath(realPath)
+}
+
+func isSensitiveSSHPath(path string) bool {
+ cleanedPath := filepath.Clean(path)
+ parts := strings.Split(filepath.ToSlash(cleanedPath), "/")
+ for i, part := range parts {
+ if part != ".ssh" {
+ continue
+ }
+ if i == len(parts)-1 {
+ return true
+ }
+ return !strings.HasSuffix(parts[len(parts)-1], ".pub")
+ }
return false
}
diff --git a/frontend/src/components/router-button/index.vue b/frontend/src/components/router-button/index.vue
index 48ff83df0..3783fce7e 100644
--- a/frontend/src/components/router-button/index.vue
+++ b/frontend/src/components/router-button/index.vue
@@ -24,8 +24,9 @@