CVE-2023-37477: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') (CWE-78)
value: 1Panel is an open source Linux server operation and maintenance management panel. An OS command injection vulnerability exists in 1Panel firewall functionality. A specially-crafted HTTP request can lead to arbitrary command execution. An attacker can make an authenticated HTTP request to trigger this vulnerability. 1Panel firewall functionality `/hosts/firewall/ip` endpoint read user input without validation, the attacker extends the default functionality of the application, which execute system commands. An attacker can execute arbitrary code on the target system, which can lead to a complete compromise of the system. This issue has been addressed in commit `e17b80cff49` which is included in release version `1.4.3`. Users are advised to upgrade. There are no known workarounds for this vulnerability.

CWE description: The product constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.
CVSS v3 base score: 8.8
Published: 2023-07-18T19:15Z
Repository: https://github.com/1Panel-dev/1Panel
Language: Go
Files changed: backend/app/service/container.go, backend/app/service/container_compose.go, backend/app/service/database_mysql.go, backend/app/service/firewall.go, backend/app/service/image_repo.go, backend/app/service/ssh.go, backend/constant/errs.go, backend/i18n/lang/en.yaml, backend/i18n/lang/zh-Hant.yaml, backend/i18n/lang/zh.yaml, backend/utils/firewall/client/firewalld.go, backend/utils/firewall/client/ufw.go
Commit date: 2023-07-17 08:34:29 +0000
Commit message: fix: 解决部分接口命令注入问题 (#1690)



Diff: diff --git a/backend/app/service/container.go b/backend/app/service/container.go
index fde34c9d..2bd94799 100644
--- a/backend/app/service/container.go
+++ b/backend/app/service/container.go
@@ -16,10 +16,11 @@ import (
 
 	"github.com/1Panel-dev/1Panel/backend/app/dto"
 	"github.com/1Panel-dev/1Panel/backend/buserr"
 	"github.com/1Panel-dev/1Panel/backend/constant"
 	"github.com/1Panel-dev/1Panel/backend/global"
+	"github.com/1Panel-dev/1Panel/backend/utils/cmd"
 	"github.com/1Panel-dev/1Panel/backend/utils/common"
 	"github.com/1Panel-dev/1Panel/backend/utils/docker"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/api/types/filters"
@@ -550,10 +551,13 @@ func (u *ContainerService) ContainerLogClean(req dto.OperationWithName) error {
 	}
 	return nil
 }
 
 func (u *ContainerService) ContainerLogs(wsConn *websocket.Conn, container, since, tail string, follow bool) error {
+	if cmd.CheckIllegal(container, since, tail) {
+		return buserr.New(constant.ErrCmdIllegal)
+	}
 	command := fmt.Sprintf("docker logs %s", container)
 	if tail != "0" {
 		command += " -n " + tail
 	}
 	if since != "all" {
diff --git a/backend/app/service/container_compose.go b/backend/app/service/container_compose.go
index 52275a95..c092bd11 100644
--- a/backend/app/service/container_compose.go
+++ b/backend/app/service/container_compose.go
@@ -12,12 +12,14 @@ import (
 	"strings"
 	"time"
 
 	"github.com/1Panel-dev/1Panel/backend/app/dto"
 	"github.com/1Panel-dev/1Panel/backend/app/model"
+	"github.com/1Panel-dev/1Panel/backend/buserr"
 	"github.com/1Panel-dev/1Panel/backend/constant"
 	"github.com/1Panel-dev/1Panel/backend/global"
+	"github.com/1Panel-dev/1Panel/backend/utils/cmd"
 	"github.com/1Panel-dev/1Panel/backend/utils/compose"
 	"github.com/1Panel-dev/1Panel/backend/utils/docker"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"golang.org/x/net/context"
@@ -125,10 +127,13 @@ func (u *ContainerService) PageCompose(req dto.SearchWithPage) (int64, interface
 	}
 	return int64(total), BackDatas, nil
 }
 
 func (u *ContainerService) TestCompose(req dto.ComposeCreate) (bool, error) {
+	if cmd.CheckIllegal(req.Path) {
+		return false, buserr.New(constant.ErrCmdIllegal)
+	}
 	composeItem, _ := composeRepo.GetRecord(commonRepo.WithByName(req.Name))
 	if composeItem.ID != 0 {
 		return false, constant.ErrRecordExist
 	}
 	if err := u.loadPath(&req); err != nil {
@@ -141,10 +146,13 @@ func (u *ContainerService) TestCompose(req dto.ComposeCreate) (bool, error) {
 	}
 	return true, nil
 }
 
 func (u *ContainerService) CreateCompose(req dto.ComposeCreate) (string, error) {
+	if cmd.CheckIllegal(req.Name, req.Path) {
+		return "", buserr.New(constant.ErrCmdIllegal)
+	}
 	if err := u.loadPath(&req); err != nil {
 		return "", err
 	}
 	global.LOG.Infof("docker-compose.yml %s create successful, start to docker-compose up", req.Name)
 
@@ -175,10 +183,13 @@ func (u *ContainerService) CreateCompose(req dto.ComposeCreate) (string, error)
 
 	return logName, nil
 }
 
 func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error {
+	if cmd.CheckIllegal(req.Path, req.Operation) {
+		return buserr.New(constant.ErrCmdIllegal)
+	}
 	if _, err := os.Stat(req.Path); err != nil {
 		return fmt.Errorf("load file with path %s failed, %v", req.Path, err)
 	}
 	if stdout, err := compose.Operate(req.Path, req.Operation); err != nil {
 		return errors.New(string(stdout))
@@ -193,10 +204,13 @@ func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error {
 
 	return nil
 }
 
 func (u *ContainerService) ComposeUpdate(req dto.ComposeUpdate) error {
+	if cmd.CheckIllegal(req.Name, req.Path) {
+		return buserr.New(constant.ErrCmdIllegal)
+	}
 	if _, err := os.Stat(req.Path); err != nil {
 		return fmt.Errorf("load file with path %s failed, %v", req.Path, err)
 	}
 	file, err := os.OpenFile(req.Path, os.O_WRONLY|os.O_TRUNC, 0640)
 	if err != nil {
diff --git a/backend/app/service/database_mysql.go b/backend/app/service/database_mysql.go
index 41755ada..0a362443 100644
--- a/backend/app/service/database_mysql.go
+++ b/backend/app/service/database_mysql.go
@@ -15,10 +15,11 @@ import (
 	"github.com/1Panel-dev/1Panel/backend/app/dto"
 	"github.com/1Panel-dev/1Panel/backend/app/model"
 	"github.com/1Panel-dev/1Panel/backend/buserr"
 	"github.com/1Panel-dev/1Panel/backend/constant"
 	"github.com/1Panel-dev/1Panel/backend/global"
+	"github.com/1Panel-dev/1Panel/backend/utils/cmd"
 	"github.com/1Panel-dev/1Panel/backend/utils/common"
 	"github.com/1Panel-dev/1Panel/backend/utils/compose"
 	_ "github.com/go-sql-driver/mysql"
 	"github.com/jinzhu/copier"
 	"github.com/pkg/errors"
@@ -75,10 +76,14 @@ var formatMap = map[string]string{
 	"gbk":     "gbk_chinese_ci",
 	"big5":    "big5_chinese_ci",
 }
 
 func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*model.DatabaseMysql, error) {
+	if cmd.CheckIllegal(req.Name, req.Username, req.Password, req.Format, req.Permission) {
+		return nil, buserr.New(constant.ErrCmdIllegal)
+	}
+
 	if req.Username == "root" {
 		return nil, errors.New("Cannot set root as user name")
 	}
 	app, err := appInstallRepo.LoadBaseInfo("mysql", "")
 	if err != nil {
@@ -182,10 +187,14 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error
 	_ = mysqlRepo.Delete(ctx, commonRepo.WithByID(db.ID))
 	return nil
 }
 
 func (u *MysqlService) ChangePassword(info dto.ChangeDBInfo) error {
+	if cmd.CheckIllegal(info.Value) {
+		return buserr.New(constant.ErrCmdIllegal)
+	}
+
 	var (
 		mysql model.DatabaseMysql
 		err   error
 	)
 	if info.ID != 0 {
@@ -251,10 +260,13 @@ func (u *MysqlService) ChangePassword(info dto.ChangeDBInfo) error {
 	}
 	return nil
 }
 
 func (u *MysqlService) ChangeAccess(info dto.ChangeDBInfo) error {
+	if cmd.CheckIllegal(info.Value) {
+		return buserr.New(constant.ErrCmdIllegal)
+	}
 	var (
 		mysql model.DatabaseMysql
 		err   error
 	)
 	if info.ID != 0 {
diff --git a/backend/app/service/firewall.go b/backend/app/service/firewall.go
index 600f132d..e010c34e 100644
--- a/backend/app/service/firewall.go
+++ b/backend/app/service/firewall.go
@@ -302,11 +302,10 @@ func OperateFirewallPort(oldPorts, newPorts []int) error {
 	client, err := firewall.NewFirewallClient()
 	if err != nil {
 		return err
 	}
 	for _, port := range newPorts {
-
 		if err := client.Port(fireClient.FireInfo{Port: strconv.Itoa(port), Protocol: "tcp", Strategy: "accept"}, "add"); err != nil {
 			return err
 		}
 	}
 	for _, port := range oldPorts {
diff --git a/backend/app/service/image_repo.go b/backend/app/service/image_repo.go
index c0d0bcbd..c38868d5 100644
--- a/backend/app/service/image_repo.go
+++ b/backend/app/service/image_repo.go
@@ -77,11 +77,11 @@ func (u *ImageRepoService) List() ([]dto.ImageRepoOption, error) {
 	return dtoOps, err
 }
 
 func (u *ImageRepoService) Create(req dto.ImageRepoCreate) error {
 	if cmd.CheckIllegal(req.Username, req.Password, req.DownloadUrl) {
-		return buserr.New(constant.ErrRepoConn)
+		return buserr.New(constant.ErrCmdIllegal)
 	}
 	imageRepo, _ := imageRepoRepo.Get(commonRepo.WithByName(req.Name))
 	if imageRepo.ID != 0 {
 		return constant.ErrRecordExist
 	}
@@ -146,11 +146,11 @@ func (u *ImageRepoService) BatchDelete(req dto.ImageRepoDelete) error {
 func (u *ImageRepoService) Update(req dto.ImageRepoUpdate) error {
 	if req.ID == 1 {
 		return errors.New("The default value cannot be deleted !")
 	}
 	if cmd.CheckIllegal(req.Username, req.Password, req.DownloadUrl) {
-		return buserr.New(constant.ErrRepoConn)
+		return buserr.New(constant.ErrCmdIllegal)
 	}
 	repo, err := imageRepoRepo.Get(commonRepo.WithByID(req.ID))
 	if err != nil {
 		return err
 	}
diff --git a/backend/app/service/ssh.go b/backend/app/service/ssh.go
index be86df3b..d975be80 100644
--- a/backend/app/service/ssh.go
+++ b/backend/app/service/ssh.go
@@ -9,10 +9,11 @@ import (
 	"sort"
 	"strings"
 	"time"
 
 	"github.com/1Panel-dev/1Panel/backend/app/dto"
+	"github.com/1Panel-dev/1Panel/backend/buserr"
 	"github.com/1Panel-dev/1Panel/backend/constant"
 	"github.com/1Panel-dev/1Panel/backend/global"
 	"github.com/1Panel-dev/1Panel/backend/utils/cmd"
 	"github.com/1Panel-dev/1Panel/backend/utils/common"
 	"github.com/1Panel-dev/1Panel/backend/utils/files"
@@ -144,10 +145,13 @@ func (u *SSHService) UpdateByFile(value string) error {
 	_, _ = cmd.Execf("%s systemctl restart sshd", sudo)
 	return nil
 }
 
 func (u *SSHService) GenerateSSH(req dto.GenerateSSH) error {
+	if cmd.CheckIllegal(req.EncryptionMode, req.Password) {
+		return buserr.New(constant.ErrCmdIllegal)
+	}
 	currentUser, err := user.Current()
 	if err != nil {
 		return fmt.Errorf("load current user failed, err: %v", err)
 	}
 	secretFile := fmt.Sprintf("%s/.ssh/id_item_%s", currentUser.HomeDir, req.EncryptionMode)
diff --git a/backend/constant/errs.go b/backend/constant/errs.go
index f3fd6fdb..873a9a29 100644
--- a/backend/constant/errs.go
+++ b/backend/constant/errs.go
@@ -40,10 +40,11 @@ var (
 	ErrTypeInvalidParams   = "ErrInvalidParams"
 	ErrTypeNotLogin        = "ErrNotLogin"
 	ErrTypePasswordExpired = "ErrPasswordExpired"
 	ErrNameIsExist         = "ErrNameIsExist"
 	ErrDemoEnvironment     = "ErrDemoEnvironment"
+	ErrCmdIllegal          = "ErrCmdIllegal"
 )
 
 // app
 var (
 	ErrPortInUsed          = "ErrPortInUsed"
@@ -105,11 +106,10 @@ var (
 // container
 var (
 	ErrInUsed       = "ErrInUsed"
 	ErrObjectInUsed = "ErrObjectInUsed"
 	ErrPortRules    = "ErrPortRules"
-	ErrRepoConn     = "ErrRepoConn"
 )
 
 // runtime
 var (
 	ErrDirNotFound    = "ErrDirNotFound"
diff --git a/backend/i18n/lang/en.yaml b/backend/i18n/lang/en.yaml
index a64e4a0e..9e5611a7 100644
--- a/backend/i18n/lang/en.yaml
+++ b/backend/i18n/lang/en.yaml
@@ -11,10 +11,11 @@ ErrNotSupportType: "The system does not support the current type: {{ .detail }}"
 
 #common
 ErrNameIsExist: "Name is already exist"
 ErrDemoEnvironment: "Demo server, prohibit this operation!"
 ErrCmdTimeout: "Command execution timed out！"
+ErrCmdIllegal: "The command contains illegal characters. Please modify and try again!"
 
 #app
 ErrPortInUsed: "{{ .detail }} port already in use"
 ErrAppLimit: "App exceeds install limit"
 ErrAppRequired: "{{ .detail }} app is required"
@@ -81,11 +82,10 @@ ErrExecTimeOut: "SQL execution timed out, please check the {{ .detail }} contain
 ErrTypeOfRedis: "The recovery file type does not match the current persistence mode. Modify the file type and try again"
 
 #container 
 ErrInUsed: "{{ .detail }} is in use and cannot be deleted"
 ErrObjectInUsed: "This object is in use and cannot be deleted"
-ErrRepoConn: "The repository information contains illegal characters"
 ErrPortRules: "The number of ports does not match, please re-enter!"
 
 #runtime
 ErrDirNotFound: "The build folder does not exist! Please check file integrity！"
 ErrFileNotExist: "{{ .detail }} file does not exist! Please check source file integrity！"
diff --git a/backend/i18n/lang/zh-Hant.yaml b/backend/i18n/lang/zh-Hant.yaml
index 33d19642..36011683 100644
--- a/backend/i18n/lang/zh-Hant.yaml
+++ b/backend/i18n/lang/zh-Hant.yaml
@@ -11,10 +11,11 @@ ErrNotSupportType: "系統暫不支持當前類型: {{ .detail }}"
 
 #common
 ErrNameIsExist: "名稱已存在"
 ErrDemoEnvironment: "演示伺服器，禁止此操作!"
 ErrCmdTimeout: "指令執行超時！"
+ErrCmdIllegal: "執行命令中存在不合法字符，請修改後重試！"
 
 #app
 ErrPortInUsed: "{{ .detail }} 端口已被佔用！"
 ErrAppLimit: "應用超出安裝數量限制"
 ErrAppRequired: "請先安裝 {{ .detail }} 應用"
@@ -81,11 +82,10 @@ ErrExecTimeOut: "SQL 執行超時，請檢查{{ .detail }}容器"
 ErrTypeOfRedis: "恢復文件類型與當前持久化方式不符，請修改後重試"
 
 #container
 ErrInUsed: "{{ .detail }} 正被使用，無法刪除"
 ErrObjectInUsed: "該對象正被使用，無法刪除"
-ErrRepoConn: "倉庫資訊中存在不合法的字符"
 ErrPortRules: "端口數目不匹配，請重新輸入！"
 
 #runtime
 ErrDirNotFound: "build 文件夾不存在！請檢查文件完整性！"
 ErrFileNotExist: "{{ .detail }} 文件不存在！請檢查源文件完整性！"
diff --git a/backend/i18n/lang/zh.yaml b/backend/i18n/lang/zh.yaml
index 162f3c67..9072be46 100644
--- a/backend/i18n/lang/zh.yaml
+++ b/backend/i18n/lang/zh.yaml
@@ -11,10 +11,11 @@ ErrNotSupportType: "系统暂不支持当前类型: {{ .detail }}"
 
 #common
 ErrNameIsExist: "名称已存在"
 ErrDemoEnvironment: "演示服务器，禁止此操作!"
 ErrCmdTimeout: "命令执行超时！"
+ErrCmdIllegal: "执行命令中存在不合法字符，请修改后重试！"
 
 #app
 ErrPortInUsed: "{{ .detail }} 端口已被占用！"
 ErrAppLimit: "应用超出安装数量限制"
 ErrAppRequired: "请先安装 {{ .detail }} 应用"
@@ -81,11 +82,10 @@ ErrExecTimeOut: "SQL 执行超时，请检查{{ .detail }}容器"
 ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符，请修改后重试"
 
 #container 
 ErrInUsed: "{{ .detail }} 正被使用，无法删除"
 ErrObjectInUsed: "该对象正被使用，无法删除"
-ErrRepoConn: "仓库信息中存在不合法的字符"
 ErrPortRules: "端口数目不匹配，请重新输入！"
 
 #runtime
 ErrDirNotFound: "build 文件夹不存在！请检查文件完整性！"
 ErrFileNotExist: "{{ .detail }} 文件不存在！请检查源文件完整性！"
diff --git a/backend/utils/firewall/client/firewalld.go b/backend/utils/firewall/client/firewalld.go
index 3f61b67c..d44e2a1c 100644
--- a/backend/utils/firewall/client/firewalld.go
+++ b/backend/utils/firewall/client/firewalld.go
@@ -2,10 +2,12 @@ package client
 
 import (
 	"fmt"
 	"strings"
 
+	"github.com/1Panel-dev/1Panel/backend/buserr"
+	"github.com/1Panel-dev/1Panel/backend/constant"
 	"github.com/1Panel-dev/1Panel/backend/utils/cmd"
 )
 
 type Firewall struct{}
 
@@ -112,18 +114,25 @@ func (f *Firewall) ListAddress() ([]FireInfo, error) {
 	}
 	return datas, nil
 }
 
 func (f *Firewall) Port(port FireInfo, operation string) error {
+	if cmd.CheckIllegal(operation, port.Protocol, port.Port) {
+		return buserr.New(constant.ErrCmdIllegal)
+	}
+
 	stdout, err := cmd.Execf("firewall-cmd --zone=public --%s-port=%s/%s --permanent", operation, port.Port, port.Protocol)
 	if err != nil {
 		return fmt.Errorf("%s port failed, err: %s", operation, stdout)
 	}
 	return nil
 }
 
 func (f *Firewall) RichRules(rule FireInfo, operation string) error {
+	if cmd.CheckIllegal(operation, rule.Address, rule.Protocol, rule.Port, rule.Strategy) {
+		return buserr.New(constant.ErrCmdIllegal)
+	}
 	ruleStr := ""
 	if strings.Contains(rule.Address, "-") {
 		std, err := cmd.Execf("firewall-cmd --permanent --new-ipset=%s --type=hash:ip", rule.Address)
 		if err != nil {
 			return fmt.Errorf("add new ipset failed, err: %s", std)
diff --git a/backend/utils/firewall/client/ufw.go b/backend/utils/firewall/client/ufw.go
index 72c7d1f9..acf070e7 100644
--- a/backend/utils/firewall/client/ufw.go
+++ b/backend/utils/firewall/client/ufw.go
@@ -2,10 +2,12 @@ package client
 
 import (
 	"fmt"
 	"strings"
 
+	"github.com/1Panel-dev/1Panel/backend/buserr"
+	"github.com/1Panel-dev/1Panel/backend/constant"
 	"github.com/1Panel-dev/1Panel/backend/utils/cmd"
 )
 
 type Ufw struct {
 	CmdStr string
@@ -129,10 +131,13 @@ func (f *Ufw) Port(port FireInfo, operation string) error {
 	case "drop":
 		port.Strategy = "deny"
 	default:
 		return fmt.Errorf("unsupport strategy %s", port.Strategy)
 	}
+	if cmd.CheckIllegal(port.Protocol, port.Port) {
+		return buserr.New(constant.ErrCmdIllegal)
+	}
 
 	command := fmt.Sprintf("%s %s %s", f.CmdStr, port.Strategy, port.Port)
 	if operation == "remove" {
 		command = fmt.Sprintf("%s delete %s %s", f.CmdStr, port.Strategy, port.Port)
 	}
@@ -154,10 +159,14 @@ func (f *Ufw) RichRules(rule FireInfo, operation string) error {
 		rule.Strategy = "deny"
 	default:
 		return fmt.Errorf("unsupport strategy %s", rule.Strategy)
 	}
 
+	if cmd.CheckIllegal(operation, rule.Protocol, rule.Address, rule.Port) {
+		return buserr.New(constant.ErrCmdIllegal)
+	}
+
 	ruleStr := fmt.Sprintf("%s %s ", f.CmdStr, rule.Strategy)
 	if operation == "remove" {
 		ruleStr = fmt.Sprintf("%s delete %s ", f.CmdStr, rule.Strategy)
 	}
 	if len(rule.Protocol) != 0 {

Vulnerable code: 
		return buserr.New(constant.ErrRepoConn)
		return buserr.New(constant.ErrRepoConn)
	ErrRepoConn     = "ErrRepoConn"
ErrRepoConn: "The repository information contains illegal characters"
ErrRepoConn: "倉庫資訊中存在不合法的字符"
ErrRepoConn: "仓库信息中存在不合法的字符"
Fixed code: 	"github.com/1Panel-dev/1Panel/backend/utils/cmd"
	if cmd.CheckIllegal(container, since, tail) {
		return buserr.New(constant.ErrCmdIllegal)
	}
	"github.com/1Panel-dev/1Panel/backend/buserr"
	"github.com/1Panel-dev/1Panel/backend/utils/cmd"
	if cmd.CheckIllegal(req.Path) {
		return false, buserr.New(constant.ErrCmdIllegal)
	}
	if cmd.CheckIllegal(req.Name, req.Path) {
		return "", buserr.New(constant.ErrCmdIllegal)
	}
	if cmd.CheckIllegal(req.Path, req.Operation) {
		return buserr.New(constant.ErrCmdIllegal)
	}
	if cmd.CheckIllegal(req.Name, req.Path) {
		return buserr.New(constant.ErrCmdIllegal)
	}
	"github.com/1Panel-dev/1Panel/backend/utils/cmd"
	if cmd.CheckIllegal(req.Name, req.Username, req.Password, req.Format, req.Permission) {
		return nil, buserr.New(constant.ErrCmdIllegal)
	}

	if cmd.CheckIllegal(info.Value) {
		return buserr.New(constant.ErrCmdIllegal)
	}

	if cmd.CheckIllegal(info.Value) {
		return buserr.New(constant.ErrCmdIllegal)
	}
		return buserr.New(constant.ErrCmdIllegal)
		return buserr.New(constant.ErrCmdIllegal)
	"github.com/1Panel-dev/1Panel/backend/buserr"
	if cmd.CheckIllegal(req.EncryptionMode, req.Password) {
		return buserr.New(constant.ErrCmdIllegal)
	}
	ErrCmdIllegal          = "ErrCmdIllegal"
ErrCmdIllegal: "The command contains illegal characters. Please modify and try again!"
ErrCmdIllegal: "執行命令中存在不合法字符，請修改後重試！"
ErrCmdIllegal: "执行命令中存在不合法字符，请修改后重试！"
	"github.com/1Panel-dev/1Panel/backend/buserr"
	"github.com/1Panel-dev/1Panel/backend/constant"
	if cmd.CheckIllegal(operation, port.Protocol, port.Port) {
		return buserr.New(constant.ErrCmdIllegal)
	}

	if cmd.CheckIllegal(operation, rule.Address, rule.Protocol, rule.Port, rule.Strategy) {
		return buserr.New(constant.ErrCmdIllegal)
	}
	"github.com/1Panel-dev/1Panel/backend/buserr"
	"github.com/1Panel-dev/1Panel/backend/constant"
	if cmd.CheckIllegal(port.Protocol, port.Port) {
		return buserr.New(constant.ErrCmdIllegal)
	}
	if cmd.CheckIllegal(operation, rule.Protocol, rule.Address, rule.Port) {
		return buserr.New(constant.ErrCmdIllegal)
	}