fix(restore): sanitize config file path to prevent zip slip

Use filepath.Base() on the config file name from the zip archive
before passing it to os.OpenFile, ensuring the config file is
always written to the current directory regardless of what path
the zip entry claims to have.
This commit is contained in:
kolaente 2026-02-24 20:07:32 +01:00
parent 12dca5f0b0
commit 7971500467
1 changed files with 5 additions and 2 deletions

View File

@ -379,7 +379,10 @@ func restoreConfig(configFile, dotEnvFile *zip.File) error {
return fmt.Errorf("config file too large, is %d, max size is %d", configFile.UncompressedSize64, maxConfigSize)
}
outFile, err := os.OpenFile(configFile.Name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, configFile.Mode())
// Use only the base name to prevent writing outside the working directory
sanitizedName := filepath.Base(configFile.Name)
outFile, err := os.OpenFile(sanitizedName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, configFile.Mode())
if err != nil {
return fmt.Errorf("could not open config file for writing: %w", err)
}
@ -398,7 +401,7 @@ func restoreConfig(configFile, dotEnvFile *zip.File) error {
_ = cfgr.Close()
_ = outFile.Close()
log.Infof("The config file has been restored to '%s'.", configFile.Name)
log.Infof("The config file has been restored to '%s'.", sanitizedName)
log.Infof("You can now make changes to it, hit enter when you're done.")
if _, err := bufio.NewReader(os.Stdin).ReadString('\n'); err != nil {
return fmt.Errorf("could not read from stdin: %w", err)