Skip to content

安全模式 ​

安全模式提供危险模式检测功能,防止 JSON 注入攻击、原型污染和其他安全威胁。

DangerousPattern 结构体 ​

DangerousPattern 表示一个安全风险模式。它是一个结构体类型。

go
type DangerousPattern struct {
    Pattern string       // 要在输入中检测的子字符串
    Name    string       // 模式的描述性名称
    Level   PatternLevel // 确定如何处理该模式的严重级别
}

字段说明 ​

字段类型说明
Patternstring要在输入中检测的子字符串
Namestring模式的描述性名称
LevelPatternLevel确定如何处理该模式的严重级别

PatternLevel 类型 ​

PatternLevel 表示危险模式的严重级别。

go
type PatternLevel int

常量 ​

go
const (
    // PatternLevelCritical 始终阻止操作
    // 用于立即构成安全风险的模式(如原型污染)
    PatternLevelCritical PatternLevel = iota

    // PatternLevelWarning 在严格模式下阻止,在宽松模式下记录警告
    // 用于可能表明恶意意图但有合法用途的模式
    PatternLevelWarning

    // PatternLevelInfo 仅记录,从不阻止
    // 用于审计/跟踪目的,不中断操作
    PatternLevelInfo
)

String 方法 ​

go
func (pl PatternLevel) String() string

返回 PatternLevel 的字符串表示("critical"、"warning"、"info"、未知值返回 "unknown")。

PatternLevel 行为矩阵 ​

级别语义意图(接口文档)当前实现的实际行为
PatternLevelCritical始终阻止操作命中即拒绝(ErrSecurityViolation)
PatternLevelWarning严格模式下阻止,宽松模式记录警告同样命中即拒绝——StrictMode 字段当前不参与模式拦截决策
PatternLevelInfo仅记录,从不阻止同样命中即拒绝

请按「会拦截」规划 Warning/Info 模式

当前版本的模式扫描(内置模式、Config.AdditionalDangerousPatterns、全局注册模式三者走同一扫描路径)对任何通过词边界上下文检查的命中都会拒绝操作,Level 不改变拦截结果,仅作为语义标注供审计/日志区分严重度。因此不要注册一个「只想记录、不想拦截」的 PatternLevelInfo 级模式并放行含该模式的输入——它今天会拦截。所有匹配均为大小写不敏感。


内置危险模式 ​

默认模式 ​

内部 API

内置模式列表由内部函数管理,不再作为公开 API 导出。可通过 Config 的 AdditionalDangerousPatterns 字段管理自定义模式。

以下是内置危险模式列表,全部为 Critical 级别:

模式名称类别
__proto__prototype pollution原型污染
constructor[constructor access构造器访问
prototype.prototype manipulation原型操作
<scriptscript tag injectionHTML 注入
<iframeiframe injectionHTML 注入
<objectobject injectionHTML 注入
<embedembed injectionHTML 注入
<svgsvg injectionHTML 注入
javascript:javascript protocol协议注入
vbscript:vbscript protocol协议注入
eval(dynamic code execution代码执行
setTimeout(timer manipulation代码执行
setInterval(interval manipulation代码执行
require(code injection代码执行
new function(dynamic function creation代码执行
document.cookiecookie accessDOM 访问
window.locationredirect manipulationDOM 访问
innerhtmlDOM manipulationDOM 访问
onerror, onload, onclick, onmouseover, onfocusevent handler injection事件处理器
fromcharcode(character encoding bypass编码绕过
atob(base64 decoding编码绕过
expression(CSS expression injectionCSS 注入
__defineGetter__getter definition原型污染
__defineSetter__setter definition原型污染

关键模式 ​

内部 API

GetCriticalPatterns 已转为内部函数,不再作为公开 API 导出。关键模式(__proto__、constructor[、prototype.)始终强制检查,无法禁用。

以下关键模式始终完全扫描,无论 JSON 大小如何:

模式说明
__proto__prototype pollution
constructor[constructor access
prototype.prototype manipulation

自定义模式注册 ​

自定义危险模式有两条注册途径:Config 追加(实例级,构造时固化进处理器的安全校验器)与全局注册(进程级,对所有 Processor 生效)。两者的作用域、移除方式与适用场景对照见全局注册 vs Config 追加。

Config 追加(实例级) ​

Config.AddDangerousPattern 方法向配置添加自定义危险模式:

签名:func (c *Config) AddDangerousPattern(pattern DangerousPattern)

go
cfg := json.DefaultConfig()
cfg.AddDangerousPattern(json.DangerousPattern{
    Pattern: "malicious_keyword",
    Name:    "自定义危险模式",
    Level:   json.PatternLevelCritical,
})

processor, err := json.New(cfg)
if err != nil {
    panic(err)
}
defer processor.Close()

也可以一次传入多个模式——直接设置 Config.AdditionalDangerousPatterns 字段:

go
cfg := json.DefaultConfig()
cfg.AdditionalDangerousPatterns = []json.DangerousPattern{
    {Pattern: "eval(", Name: "eval-call", Level: json.PatternLevelCritical},
    {Pattern: "exec(", Name: "exec-call", Level: json.PatternLevelWarning},
}

相关配置字段:

go
type Config struct {
    // ... 其他字段 ...

    // AdditionalDangerousPatterns 添加除默认模式外的安全模式
    AdditionalDangerousPatterns []DangerousPattern

    // DisableDefaultPatterns 禁用内置默认安全模式(关键模式除外)
    // 设为 true 则仅使用 AdditionalDangerousPatterns
    // 注意:关键模式(__proto__、constructor[、prototype.)始终强制执行,无法禁用
    DisableDefaultPatterns bool
}

全局注册(进程级) ​

除了通过 Config 配置实例级模式外,还可以通过包级函数管理全局模式注册表。全局注册表中的模式在所有 Processor 实例中生效。

RegisterDangerousPattern ​

签名:func RegisterDangerousPattern(pattern DangerousPattern)

向全局注册表添加自定义危险模式。注册的模式在所有 Processor 实例中生效。

go
json.RegisterDangerousPattern(json.DangerousPattern{
    Pattern: "malicious_keyword",
    Name:    "自定义危险模式",
    Level:   json.PatternLevelCritical,
})

UnregisterDangerousPattern ​

签名:func UnregisterDangerousPattern(pattern string)

从全局注册表中移除指定模式。

go
json.UnregisterDangerousPattern("malicious_keyword")

ListDangerousPatterns ​

签名:func ListDangerousPatterns() []DangerousPattern

返回全局注册表中所有自定义模式。

go
patterns := json.ListDangerousPatterns()
for _, p := range patterns {
    fmt.Printf("模式: %s, 名称: %s, 级别: %s\n", p.Pattern, p.Name, p.Level)
}

全局注册 vs Config 追加 ​

维度全局注册(RegisterDangerousPattern)Config 追加(AddDangerousPattern / AdditionalDangerousPatterns)
作用域进程内所有 Processor,含已创建的实例(扫描时实时读取注册表)仅使用该 Config 创建的 Processor(构造时固化进安全校验器)
移除方式UnregisterDangerousPattern(pattern) 即时生效无运行期移除,需换新 Config 重建 Processor
查询方式ListDangerousPatterns()读取 cfg.AdditionalDangerousPatterns 字段
与 DisableDefaultPatterns 的关系不受影响(显式加入的模式始终扫描)不受影响(同左)
典型用途应用级安全策略、合规黑名单,main 启动时注册单个实例的业务定制(如仅某个租户的 Processor 拦截特定关键词)

完整对比示例:

go
package main

import (
	"fmt"

	"github.com/cybergodev/json"
)

func main() {
	// 全局注册:对所有 Processor 生效(含已创建的实例)
	json.RegisterDangerousPattern(json.DangerousPattern{
		Pattern: "internal_only",
		Name:    "内部标识符",
		Level:   json.PatternLevelCritical,
	})
	defer json.UnregisterDangerousPattern("internal_only")

	// Config 追加:仅影响使用该 Config 的 Processor
	cfg := json.DefaultConfig()
	cfg.AddDangerousPattern(json.DangerousPattern{
		Pattern: "project_secret",
		Name:    "项目机密",
		Level:   json.PatternLevelCritical,
	})

	withCfg, err := json.New(cfg)
	if err != nil {
		panic(err)
	}
	defer withCfg.Close()

	withoutCfg, err := json.New(json.DefaultConfig())
	if err != nil {
		panic(err)
	}
	defer withoutCfg.Close()

	_, err1 := withCfg.Get(`{"v": "project_secret"}`, "v")
	_, err2 := withoutCfg.Get(`{"v": "project_secret"}`, "v")
	_, err3 := withoutCfg.Get(`{"v": "internal_only"}`, "v")

	fmt.Println("局部模式拦截配置处理器:", err1 != nil)
	fmt.Println("局部模式拦截普通处理器:", err2 != nil)
	fmt.Println("全局模式拦截普通处理器:", err3 != nil)
	// 输出:
	// 局部模式拦截配置处理器:true
	// 局部模式拦截普通处理器:false
	// 全局模式拦截普通处理器:true
}

完整示例 ​

自定义安全策略 ​

go
package main

import (
	"fmt"
	"github.com/cybergodev/json"
)

func main() {
	// 方式一:通过配置字段
	cfg := json.DefaultConfig()
	cfg.AdditionalDangerousPatterns = []json.DangerousPattern{
		{Pattern: "company_secret", Name: "公司敏感信息", Level: json.PatternLevelCritical},
	}

	// 方式二:通过配置方法
	cfg.AddDangerousPattern(json.DangerousPattern{
		Pattern: "internal_api",
		Name:    "内部 API 引用",
		Level:   json.PatternLevelWarning,
	})

	p, err := json.New(cfg)
	if err != nil {
		panic(err)
	}
	defer p.Close()

	// 测试危险模式检测(模式作为整词匹配:两侧不能紧邻字母/数字/下划线)
	_, err = p.Get(`{"data": "company_secret"}`, "data")
	fmt.Println("检测到危险模式:", err != nil)
	// 输出:检测到危险模式:true

	// 查看已注册的模式
	fmt.Printf("自定义模式数量:%d\n", len(cfg.AdditionalDangerousPatterns))
}

匹配是「整词」的

模式命中后会做词边界上下文检查:模式两侧紧邻字母、数字或下划线时视为普通标识符的一部分而不拦截。例如模式 company_secret 在 "company_secret" 中触发,在 "company_secret_info" 中不触发(后跟 _ 属词内字符);以 (、[、:、. 等分隔符结尾的模式(如 eval()则不受后缀影响。这也是库内置模式(如 eval(、__proto__)的匹配方式。

禁用默认模式 ​

go
cfg := json.DefaultConfig()

// 禁用内置默认模式(关键模式除外),仅使用自定义模式
// 注意:关键模式(__proto__、constructor[、prototype.)始终强制执行
cfg.DisableDefaultPatterns = true

// 添加自定义模式
cfg.AddDangerousPattern(json.DangerousPattern{
    Pattern: "xss_payload",
    Name:    "XSS 攻击载荷",
    Level:   json.PatternLevelCritical,
})

p, err := json.New(cfg)
if err != nil {
    panic(err)
}
defer p.Close()

按级别处理模式 ​

go
// 注册不同级别的模式
cfg := json.DefaultConfig()
cfg.AddDangerousPattern(json.DangerousPattern{
    Pattern: "suspicious_but_allowed",
    Name:    "可疑但允许",
    Level:   json.PatternLevelInfo, // 语义标注;当前实现命中同样会拦截(见 PatternLevel 行为矩阵)
})

// 查看已注册的自定义模式
for _, p := range cfg.AdditionalDangerousPatterns {
    fmt.Printf("模式: %s, 名称: %s, 级别: %s\n", p.Pattern, p.Name, p.Level)
}

扫描开关 ​

三个 Config 字段控制「怎么扫」:

字段默认作用
FullSecurityScanfalsetrue 时对所有输入不分大小做全量扫描;false 时小输入(< 4KB)全量、大输入走分层优化扫描(见下节,同样保证 100% 覆盖)。全量模式对 >100KB 输入约有 10–30% 额外开销
DisableDefaultPatternsfalsetrue 时跳过内置的非关键模式(HTML 标签、事件处理器等),仅保留 3 个关键模式 + 自定义模式
AdditionalDangerousPatternsnil在内置模式之外叠加自定义模式(见上文)
go
cfg := json.SecurityConfig() // 已开启 FullSecurityScan 并收紧各项限制
// 等价于手动设置:
// cfg := json.DefaultConfig()
// cfg.FullSecurityScan = true

开启建议:处理不可信输入(公网 API、用户提交、外部 webhook)、涉及敏感数据(认证、金融、个人信息)或有合规全量审计要求时启用 FullSecurityScan;可信内部服务的大报文可保持默认的分层扫描以兼顾吞吐。


安全扫描策略 ​

小 JSON(< 4KB) ​

始终进行完整的安全扫描,逐一检查全部危险模式。

较大 JSON(≥ 4KB) ​

采用多层级优化扫描,保证 100% 覆盖(无采样盲区):

  • 关键模式(__proto__、constructor[、prototype.)始终完全扫描
  • 先做指示字符检查:若无任何危险字符则快速跳过
  • 检测可疑字符密度:密度过高时回退全量扫描,防止攻击者把恶意内容藏在密集区
  • 其余模式使用 32KB 滚动窗口扫描(窗口带重叠),确保跨边界模式不遗漏

相关 ​