VYPR
Moderate severityNVD Advisory· Published Dec 9, 2025· Updated Dec 9, 2025

1Panel IP Access Control Bypass via Untrusted X-Forwarded-For Headers

CVE-2025-66508

Description

1Panel is an open-source, web-based control panel for Linux server management. Versions 2.0.14 and below use Gin's default configuration which trusts all IP addresses as proxies (TrustedProxies = 0.0.0.0/0), allowing any client to spoof the X-Forwarded-For header. Since all IP-based access controls (AllowIPs, API whitelists, localhost-only checks) rely on ClientIP(), attackers can bypass these protections by simply sending X-Forwarded-For: 127.0.0.1 or any whitelisted IP. This renders all IP-based security controls ineffective. This issue is fixed in version 2.0.14.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/1Panel-dev/1PanelGo
< 2.0.142.0.14
github.com/1Panel-dev/1Panel/agentGo
< 0.0.0-20251201063338-94f7d78cc9760.0.0-20251201063338-94f7d78cc976

Affected products

1

Patches

1
94f7d78cc976

fix: Fix iptables state persistence issue (#11137)

https://github.com/1Panel-dev/1PanelssongliuDec 1, 2025via ghsa
4 files changed · +118 41
  • agent/app/service/iptables.go+23 1 modified
    @@ -8,6 +8,7 @@ import (
     
     	"github.com/1Panel-dev/1Panel/agent/app/dto"
     	"github.com/1Panel-dev/1Panel/agent/app/model"
    +	"github.com/1Panel-dev/1Panel/agent/constant"
     	"github.com/1Panel-dev/1Panel/agent/global"
     	"github.com/1Panel-dev/1Panel/agent/utils/cmd"
     	"github.com/1Panel-dev/1Panel/agent/utils/firewall/client"
    @@ -189,9 +190,14 @@ func (s *IptablesService) Operate(req dto.IptablesOp) error {
     		if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.BasicAfterFileName); err != nil {
     			return err
     		}
    +		_ = settingRepo.Update("IptablesStatus", constant.StatusEnable)
     		return nil
     	case "init-forward":
    -		return client.EnableIptablesForward()
    +		if err := client.EnableIptablesForward(); err != nil {
    +			return err
    +		}
    +		_ = settingRepo.Update("IptablesForwardStatus", constant.StatusEnable)
    +		return nil
     	case "init-advance":
     		if err := iptables.AddChain(iptables.FilterTab, iptables.Chain1PanelInput); err != nil {
     			return err
    @@ -206,6 +212,8 @@ func (s *IptablesService) Operate(req dto.IptablesOp) error {
     		if err := iptables.BindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelInput, number); err != nil {
     			return err
     		}
    +		_ = settingRepo.Update("IptablesInputStatus", constant.StatusEnable)
    +		_ = settingRepo.Update("IptablesOutputStatus", constant.StatusEnable)
     		return nil
     	case "bind-base":
     		if err := initPreRules(); err != nil {
    @@ -220,6 +228,7 @@ func (s *IptablesService) Operate(req dto.IptablesOp) error {
     		if err := iptables.BindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicAfter, 3); err != nil {
     			return err
     		}
    +		_ = settingRepo.Update("IptablesStatus", constant.StatusEnable)
     		return nil
     	case "unbind-base":
     		if err := iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicAfter); err != nil {
    @@ -231,16 +240,29 @@ func (s *IptablesService) Operate(req dto.IptablesOp) error {
     		if err := iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasic); err != nil {
     			return err
     		}
    +		_ = settingRepo.Update("IptablesStatus", constant.StatusDisable)
     		return nil
     	case "bind":
     		if err := iptables.BindChain(iptables.FilterTab, targetChain, req.Name, loadBindNumber(req.Name)); err != nil {
     			return err
     		}
    +		if req.Name == iptables.Chain1PanelInput {
    +			_ = settingRepo.Update("IptablesInputStatus", constant.StatusEnable)
    +		}
    +		if req.Name == iptables.Chain1PanelOutput {
    +			_ = settingRepo.Update("IptablesOutputStatus", constant.StatusEnable)
    +		}
     		return nil
     	case "unbind":
     		if err := iptables.UnbindChain(iptables.FilterTab, targetChain, req.Name); err != nil {
     			return err
     		}
    +		if req.Name == iptables.Chain1PanelInput {
    +			_ = settingRepo.Update("IptablesInputStatus", constant.StatusDisable)
    +		}
    +		if req.Name == iptables.Chain1PanelOutput {
    +			_ = settingRepo.Update("IptablesOutputStatus", constant.StatusDisable)
    +		}
     		return nil
     	}
     	return nil
    
  • agent/init/firewall/firewall.go+75 40 modified
    @@ -2,21 +2,30 @@ package firewall
     
     import (
     	"fmt"
    +	"os"
     
     	"github.com/1Panel-dev/1Panel/agent/app/dto"
    +	"github.com/1Panel-dev/1Panel/agent/app/repo"
     	"github.com/1Panel-dev/1Panel/agent/app/service"
    +	"github.com/1Panel-dev/1Panel/agent/constant"
     	"github.com/1Panel-dev/1Panel/agent/global"
     	"github.com/1Panel-dev/1Panel/agent/utils/firewall"
     	firewallClient "github.com/1Panel-dev/1Panel/agent/utils/firewall/client"
     	"github.com/1Panel-dev/1Panel/agent/utils/firewall/client/iptables"
     )
     
     func Init() {
    +	if !needInit() {
    +		return
    +	}
    +	global.LOG.Info("initializing firewall settings...")
     	client, err := firewall.NewFirewallClient()
     	if err != nil {
     		return
     	}
     	clientName := client.Name()
    +
    +	settingRepo := repo.NewISettingRepo()
     	if clientName == "ufw" || clientName == "iptables" {
     		if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelForward, iptables.ForwardFileName); err != nil {
     			global.LOG.Errorf("load forward rules from file failed, err: %v", err)
    @@ -30,65 +39,91 @@ func Init() {
     			global.LOG.Errorf("load postrouting rules from file failed, err: %v", err)
     			return
     		}
    -		if err := firewallClient.EnableIptablesForward(); err != nil {
    -			global.LOG.Errorf("enable iptables forward failed, err: %v", err)
    -			return
    -		}
     		global.LOG.Infof("loaded iptables rules for forward from file successfully")
    +
    +		iptablesForwardStatus, _ := settingRepo.GetValueByKey("IptablesForwardStatus")
    +		if iptablesForwardStatus == constant.StatusEnable {
    +			if err := firewallClient.EnableIptablesForward(); err != nil {
    +				global.LOG.Errorf("enable iptables forward failed, err: %v", err)
    +				return
    +			}
    +		}
     	}
    +
     	if clientName == "ufw" {
     		_ = iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicAfter)
     		_ = iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicBefore)
     		_ = iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasic)
     		_ = iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelInput)
     		_ = iptables.UnbindChain(iptables.FilterTab, iptables.ChainOutput, iptables.Chain1PanelOutput)
     	}
    -	if clientName == "iptables" {
    -		if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.BasicBeforeFileName); err != nil {
    -			global.LOG.Errorf("load basic before rules from file failed, err: %v", err)
    -			return
    -		}
    -		if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName); err != nil {
    -			global.LOG.Errorf("load basic rules from file failed, err: %v", err)
    -			return
    -		}
    -		if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.BasicAfterFileName); err != nil {
    -			global.LOG.Errorf("load basic after rules from file failed, err: %v", err)
    -			return
    -		}
    -		if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelInput, iptables.InputFileName); err != nil {
    -			global.LOG.Errorf("load input rules from file failed, err: %v", err)
    -			return
    -		}
    -		if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelOutput, iptables.OutputFileName); err != nil {
    -			global.LOG.Errorf("load output rules from file failed, err: %v", err)
    -			return
    -		}
    -		global.LOG.Infof("loaded iptables rules for basic, input and output from file successfully")
     
    -		panelPort := service.LoadPanelPort()
    -		if len(panelPort) == 0 {
    -			global.LOG.Errorf("find 1panel service port failed")
    -			return
    -		}
    -		if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, fmt.Sprintf("-p tcp -m tcp --dport %v -j ACCEPT", panelPort)); err != nil {
    -			global.LOG.Errorf("add port accept rule %v failed, err: %v", panelPort, err)
    +	if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.BasicBeforeFileName); err != nil {
    +		global.LOG.Errorf("load basic before rules from file failed, err: %v", err)
    +		return
    +	}
    +	if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName); err != nil {
    +		global.LOG.Errorf("load basic rules from file failed, err: %v", err)
    +		return
    +	}
    +	if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.BasicAfterFileName); err != nil {
    +		global.LOG.Errorf("load basic after rules from file failed, err: %v", err)
    +		return
    +	}
    +	panelPort := service.LoadPanelPort()
    +	if len(panelPort) == 0 {
    +		global.LOG.Errorf("find 1panel service port failed")
    +		return
    +	}
    +	if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, fmt.Sprintf("-p tcp -m tcp --dport %v -j ACCEPT", panelPort)); err != nil {
    +		global.LOG.Errorf("add port accept rule %v failed, err: %v", panelPort, err)
    +		return
    +	}
    +	global.LOG.Infof("loaded iptables rules for basic from file successfully")
    +	iptablesService := service.IptablesService{}
    +	iptablesStatus, _ := settingRepo.GetValueByKey("IptablesStatus")
    +	if iptablesStatus == constant.StatusEnable {
    +		if err := iptablesService.Operate(dto.IptablesOp{Operate: "bind-base"}); err != nil {
    +			global.LOG.Errorf("bind base chains failed, err: %v", err)
     			return
     		}
    +	}
     
    -		iptablesService := service.IptablesService{}
    -		if err := iptablesService.Operate(dto.IptablesOp{Operate: "bind-base"}); err != nil {
    -			global.LOG.Errorf("bind base chains failed, err: %v", err)
    +	if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelInput, iptables.InputFileName); err != nil {
    +		global.LOG.Errorf("load input rules from file failed, err: %v", err)
    +		return
    +	}
    +	if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelOutput, iptables.OutputFileName); err != nil {
    +		global.LOG.Errorf("load output rules from file failed, err: %v", err)
    +		return
    +	}
    +	global.LOG.Infof("loaded iptables rules for input and output from file successfully")
    +	iptablesInputStatus, _ := settingRepo.GetValueByKey("IptablesInputStatus")
    +	if iptablesInputStatus == constant.StatusEnable {
    +		if err := iptablesService.Operate(dto.IptablesOp{Name: iptables.Chain1PanelInput, Operate: "bind"}); err != nil {
    +			global.LOG.Errorf("bind input chains failed, err: %v", err)
     			return
     		}
    +	}
    +	iptablesOutputStatus, _ := settingRepo.GetValueByKey("IptablesOutputStatus")
    +	if iptablesOutputStatus == constant.StatusEnable {
     		if err := iptablesService.Operate(dto.IptablesOp{Name: iptables.Chain1PanelOutput, Operate: "bind"}); err != nil {
     			global.LOG.Errorf("bind output chains failed, err: %v", err)
     			return
     		}
    -		if err := iptablesService.Operate(dto.IptablesOp{Name: iptables.Chain1PanelInput, Operate: "bind"}); err != nil {
    -			global.LOG.Errorf("bind input chains failed, err: %v", err)
    -			return
    -		}
     	}
    +}
     
    +func needInit() bool {
    +	file, err := os.OpenFile("/run/1panel_boot_mark", os.O_RDWR|os.O_CREATE|os.O_EXCL, 0644)
    +	if err != nil {
    +		if os.IsExist(err) {
    +			return false
    +		}
    +		global.LOG.Errorf("check boot mark file failed: %v", err)
    +		return true
    +	}
    +	defer file.Close()
    +	fmt.Fprintf(file, "Boot Mark for 1panel\n")
    +	return true
     }
    
  • agent/init/migration/migrate.go+1 0 modified
    @@ -56,6 +56,7 @@ func InitAgentDB() {
     		migrations.UpdateDatabase,
     		migrations.AddGPUMonitor,
     		migrations.UpdateDatabaseMysql,
    +		migrations.InitIptablesStatus,
     	})
     	if err := m.Migrate(); err != nil {
     		global.LOG.Error(err)
    
  • agent/init/migration/migrations/init.go+19 0 modified
    @@ -756,3 +756,22 @@ var UpdateDatabaseMysql = &gormigrate.Migration{
     		return nil
     	},
     }
    +
    +var InitIptablesStatus = &gormigrate.Migration{
    +	ID: "20251201-init-iptables-status",
    +	Migrate: func(tx *gorm.DB) error {
    +		if err := tx.Create(&model.Setting{Key: "IptablesStatus", Value: constant.StatusDisable}).Error; err != nil {
    +			return err
    +		}
    +		if err := tx.Create(&model.Setting{Key: "IptablesForwardStatus", Value: constant.StatusDisable}).Error; err != nil {
    +			return err
    +		}
    +		if err := tx.Create(&model.Setting{Key: "IptablesInputStatus", Value: constant.StatusDisable}).Error; err != nil {
    +			return err
    +		}
    +		if err := tx.Create(&model.Setting{Key: "IptablesOutputStatus", Value: constant.StatusDisable}).Error; err != nil {
    +			return err
    +		}
    +		return nil
    +	},
    +}
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.