Help us shape the future of Go! Take the 2026 Go Developer Survey

bashguard

package
v0.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package bashguard bash 命令静态风险解析:不执行命令,经真 shell AST (mvdan.cc/sh)解析成调用序列,按策略表判定只读性。对标 ZCode bash-command-parser.ts + bash-readonly-policy 的「权限判定不执行命令」。

判定原则(保守到宁可误报):

  • 解析失败、含动态词($() / 反引号 / 未展开 $VAR)、含写重定向、 复合控制流(if/for/while/case/函数定义)→ 一律非只读——无法静态证明 安全的就不放行;
  • 调用按策略表:命令不在表=未知(非只读);命中危险 flag=非只读; 未知 flag=非只读;值型 flag 吃一个参数后继续;
  • 安全包装(env/nice/nohup/time/timeout/stdbuf/xargs)剥壳后判定内核;
  • 复合命令(&& || ; |)每一段都必须只读,整体才只读。

三档:只读 / 写 / 不可逆

只读判定回答「会不会改东西」;**不可逆判定**(Decision.Destructive)回答 「一旦跑就收不回来」——两者正交:rm file 不是只读但可逆,rm -rf / 不可逆。 不可逆判据走**独立的一张表**(Table.Destructive,见 destructive.go): 只读表只放只读命令,而不可逆判据要覆盖 rm / mkfs / dd 这类写命令。 「要不要二次确认」是调用方的策略决定;本包给的是「这条命令不可逆」这个事实。

上限 10K 字符(对标 ZCode:超长命令不进解析器)。

缺省只读策略表:保守起步集——不在表=非只读;生产按需经 Table 自定义扩展 (对标 ZCode 的表驱动形态:每命令声明安全 flag 及其值形态)。

Index

Constants

View Source
const MaxCommandLen = 10 * 1024

MaxCommandLen 解析上限。

Variables

This section is empty.

Functions

This section is empty.

Types

type Decision

type Decision struct {
	// ReadOnly 命令可判只读(不执行任何写路径)。
	ReadOnly bool
	// Reason 非只读原因(人可读,审计用)。
	Reason string
	// Destructive 该调用含不可逆动作(删数据 / 写设备 / 关机 / 递归改权限 …)。
	//
	// 与 ReadOnly **正交**:只读与否是另一档。一个命令可以「不是只读、但可逆」
	//(rm file),也可以「不是只读、且不可逆」(rm -rf /)。
	//
	// 语义边界:false 只意味着「没命中已知规则」,**不意味着安全**——
	// 是否要二次确认是调用方的策略决定,本包只给「这条命令不可逆」这个事实。
	Destructive bool
	// DestructiveReason 不可逆依据(人可读,审计用);未命中时为空。
	DestructiveReason string
	// Invocations 提取的调用序列(观测/风险面)。
	Invocations []Invocation
}

Decision 判定结果。

func Analyze

func Analyze(cmdStr string, t *Table) Decision

Analyze 静态解析与判定。超长/解析失败返回非只读(保守)。

type FlagKind

type FlagKind string

FlagKind 值型 flag 的参数形态。

const (
	FlagBool     FlagKind = "bool"     // 不吃参数
	FlagString   FlagKind = "string"   // 吃一个任意字面参数
	FlagNumber   FlagKind = "number"   // 吃一个数值参数
	FlagOptional FlagKind = "optional" // 可带可不带参数(按字面形态分辨)
)

type Invocation

type Invocation struct {
	Name    string
	Args    []string
	Dynamic bool // 含动态词(argv 非字面)
}

Invocation 提取的单次调用(观测面)。

type Policy

type Policy struct {
	// ReadOnly 命令本体是否只读。
	ReadOnly bool
	// SafeFlags 已知安全 flag(含 - 前缀,如 "-n")。长 flag 单写。
	SafeFlags map[string]FlagKind
	// UnsafeFlags 命中即非只读(显式优先于 SafeFlags)。
	UnsafeFlags []string
	// Subcommands 子命令策略表(git 形态,可嵌套):子命令不在表=非只读。
	Subcommands map[string]Policy
	// Wrapper 安全包装(env/timeout 形态):剥壳后按剩余首参判定。
	Wrapper bool
	// ConsumeBare Wrapper 剥 flag 后先吃掉的前置裸操作数个数(timeout 的时长)。
	ConsumeBare int
	// NoBareOperands 裸操作数即写形态(git branch <名> 创建 / git stash 裸 push /
	// git tag <名> 打标):出现任何 flag 之外的裸操作数 → 非只读。
	NoBareOperands bool
	// AllowBareOperandsPrefix NoBareOperands 的豁免前缀(date 的 +FORMAT 形态:
	// 裸操作数以 "+" 开头是格式串不是写目标)。前缀空串不放行任何操作数。
	AllowBareOperandsPrefix []string
	// Destructive 该命令恒不可逆(删数据 / 写设备 / 关机 …)。
	//
	// 只在**不可逆规则表**(Table.Destructive)里有意义——只读表是只读表,
	// 不可逆判据单列一张(见 destructive.go 的说明)。
	Destructive bool
	// DestructiveFlags 命中即不可逆的 flag("-r" / "--recursive")。
	// 短 flag 支持联合形态(-rf 里的 r)。
	DestructiveFlags []string
	// DestructiveArgs 命中即不可逆的参数(**前缀**匹配:"of=" 命中 "of=/dev/sda")。
	DestructiveArgs []string
}

Policy 单命令策略。

type Table

type Table struct {
	Commands map[string]Policy
	// Destructive 不可逆规则表:命令名 → 判据(只用 Policy 的三个 Destructive* 字段)。
	//
	// 与只读表**分开**:只读表只放只读命令("不在只读策略表" 是既有语义),
	// 而不可逆判据要覆盖 rm / mkfs / dd 这类写命令。键尾的 "*" 表示前缀族
	//("mkfs*" 覆盖 mkfs.ext4 等)。
	Destructive map[string]Policy
}

Table 策略表。

func DefaultTable

func DefaultTable() *Table

DefaultTable 内置缺省策略表(副本:调用方改表不影响后续 DefaultTable)。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL