bashguard

package
v0.9.1 Latest Latest
Warning

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

Go to latest
Published: Nov 4, 2026 License: MIT Imports: 4 Imported by: 2

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