Browse Source

fix(restore): skipping symlinks outside allowed paths during restore #1371

0xJacky 2 days ago
parent
commit
29b83da8cb
2 changed files with 20 additions and 8 deletions
  1. 7 0
      app/components.d.ts
  2. 13 8
      internal/backup/restore.go

+ 7 - 0
app/components.d.ts

@@ -32,6 +32,7 @@ declare module 'vue' {
     AInput: typeof import('ant-design-vue/es')['Input']
     AInputGroup: typeof import('ant-design-vue/es')['InputGroup']
     AInputNumber: typeof import('ant-design-vue/es')['InputNumber']
+    AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
     ALayout: typeof import('ant-design-vue/es')['Layout']
     ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
     ALayoutFooter: typeof import('ant-design-vue/es')['LayoutFooter']
@@ -48,12 +49,16 @@ declare module 'vue' {
     APopover: typeof import('ant-design-vue/es')['Popover']
     AppProviderAppProvider: typeof import('./src/components/AppProvider/AppProvider.vue')['default']
     AProgress: typeof import('ant-design-vue/es')['Progress']
+    AQrcode: typeof import('ant-design-vue/es')['QRCode']
+    ARangePicker: typeof import('ant-design-vue/es')['RangePicker']
     AResult: typeof import('ant-design-vue/es')['Result']
     ARow: typeof import('ant-design-vue/es')['Row']
+    ASegmented: typeof import('ant-design-vue/es')['Segmented']
     ASelect: typeof import('ant-design-vue/es')['Select']
     ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
     ASpace: typeof import('ant-design-vue/es')['Space']
     ASpin: typeof import('ant-design-vue/es')['Spin']
+    AStatistic: typeof import('ant-design-vue/es')['Statistic']
     AStep: typeof import('ant-design-vue/es')['Step']
     ASteps: typeof import('ant-design-vue/es')['Steps']
     ASubMenu: typeof import('ant-design-vue/es')['SubMenu']
@@ -64,6 +69,8 @@ declare module 'vue' {
     ATag: typeof import('ant-design-vue/es')['Tag']
     ATextarea: typeof import('ant-design-vue/es')['Textarea']
     ATooltip: typeof import('ant-design-vue/es')['Tooltip']
+    ATypographyText: typeof import('ant-design-vue/es')['TypographyText']
+    ATypographyTitle: typeof import('ant-design-vue/es')['TypographyTitle']
     AutoCertFormAutoCertForm: typeof import('./src/components/AutoCertForm/AutoCertForm.vue')['default']
     AutoCertFormDNSChallenge: typeof import('./src/components/AutoCertForm/DNSChallenge.vue')['default']
     BaseEditorBaseEditor: typeof import('./src/components/BaseEditor/BaseEditor.vue')['default']

+ 13 - 8
internal/backup/restore.go

@@ -11,6 +11,7 @@ import (
 	"github.com/0xJacky/Nginx-UI/internal/nginx"
 	"github.com/0xJacky/Nginx-UI/settings"
 	"github.com/uozi-tech/cosy"
+	"github.com/uozi-tech/cosy/logger"
 	cosysettings "github.com/uozi-tech/cosy/settings"
 )
 
@@ -239,20 +240,24 @@ func extractZipFile(file *zip.File, destDir string) error {
 				return nil
 			}
 
-			// Otherwise, fallback to creating a directory
-			if err := os.MkdirAll(filePath, 0755); err != nil {
-				return cosy.WrapErrorWithParams(ErrCreateDir, fmt.Sprintf("failed to create directory %s: %v", filePath, err))
-			}
+			// Skip symlinks that point to paths outside the allowed directories
+			logger.Warn("Skipping symlink outside allowed paths during restore",
+				"path", filePath,
+				"target", cleanLinkTarget,
+				"allowedConfPath", confPath,
+				"allowedModulesPath", modulesPath)
 			return nil
 		}
 
 		// For relative symlinks, verify they don't escape the destination directory
 		absLinkTarget := filepath.Clean(filepath.Join(filepath.Dir(filePath), cleanLinkTarget))
 		if !strings.HasPrefix(absLinkTarget, destDirAbs+string(os.PathSeparator)) {
-			// Create directory instead of symlink if the target is outside destination
-			if err := os.MkdirAll(filePath, 0755); err != nil {
-				return cosy.WrapErrorWithParams(ErrCreateDir, fmt.Sprintf("failed to create directory %s: %v", filePath, err))
-			}
+			// Skip relative symlinks that point outside the destination directory
+			logger.Warn("Skipping relative symlink pointing outside destination directory during restore",
+				"path", filePath,
+				"target", cleanLinkTarget,
+				"resolvedTarget", absLinkTarget,
+				"destinationDir", destDirAbs)
 			return nil
 		}