第6讲:Agent 安全

一、Agent 安全威胁全景

复制代码
Agent 安全攻击面
                           │
        ┌──────────────────┼──────────────────┐
        │                  │                  │
   ┌────▼────┐      ┌─────▼─────┐     ┌─────▼─────┐
   │ Prompt   │      │ 工具调用    │     │ 记忆/状态   │
   │ 注入攻击  │      │ 滥用       │     │ 污染       │
   └──────────┘      └───────────┘     └───────────┘
        │                  │                  │
   ┌────▼────┐      ┌─────▼─────┐     ┌─────▼─────┐
   │ 间接注入  │      │ 命令执行    │     │ 会话劫持    │
   │ 恶意指令  │      │ 资源耗尽    │     │ 数据投毒    │
   └──────────┘      └───────────┘     └───────────┘
        │                  │                  │
   ┌────▼────┐      ┌─────▼─────┐     ┌─────▼─────┐
   │ 供应链    │      │ 权限提升    │     │ 推理攻击    │
   │ 攻击      │      │ 越权操作    │     │ 隐私泄露    │
   └──────────┘      └───────────┘     └───────────┘

Agent 安全四大维度

维度 威胁 影响等级
Prompt 安全​ 间接注入、恶意指令覆盖 严重
工具安全​ 命令注入、资源耗尽、权限滥用 严重
记忆安全​ 会话污染、长期记忆投毒 高危
供应链安全​ 恶意插件、依赖劫持 高危

二、Agent 核心架构

复制代码
package main

import (
	"context"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"log"
	"math"
	"os/exec"
	"regexp"
	"strings"
	"sync"
	"time"
)

// ============================================================
// 1. 基础数据结构
// ============================================================

type AgentID string
type SessionID string
type ToolID string
type PermissionLevel int

const (
	PermissionReadOnly  PermissionLevel = iota // 只读
	PermissionRestricted                       // 受限
	PermissionStandard                         // 标准
	PermissionElevated                         // 提权
	PermissionAdmin                            // 管理员
)

type AgentContext struct {
	AgentID    AgentID          `json:"agent_id"`
	SessionID  SessionID        `json:"session_id"`
	UserID     string           `json:"user_id"`
	Permissions map[string]PermissionLevel `json:"permissions"`
	ToolCalls  []ToolCallRecord `json:"tool_calls"`
	StartTime  time.Time        `json:"start_time"`
	ExpiresAt  time.Time        `json:"expires_at"`
	Metadata   map[string]interface{} `json:"metadata,omitempty"`
}

type ToolCallRecord struct {
	ToolID     ToolID            `json:"tool_id"`
	Action     string            `json:"action"`
	Params     map[string]interface{} `json:"params"`
	ResultHash string            `json:"result_hash"`
	Timestamp  time.Time         `json:"timestamp"`
	Duration   time.Duration     `json:"duration"`
	Allowed    bool              `json:"allowed"`
	Reason     string            `json:"reason,omitempty"`
}

// ============================================================
// 2. 工具沙箱
// ============================================================

type ToolSandbox struct {
	tools     map[ToolID]*RegisteredTool
	policy    *AccessPolicy
	auditLog  *AuditLogger
	rateLimit *RateLimiter
	mu        sync.RWMutex
}

type RegisteredTool struct {
	ID          ToolID                 `json:"id"`
	Name        string                 `json:"name"`
	Description string                 `json:"description"`
	Version     string                 `json:"version"`
	RequiredPerm PermissionLevel       `json:"required_permission"`
	Validator   func(params map[string]interface{}) error `json:"-"`
	Executor    func(ctx context.Context, params map[string]interface{}) (interface{}, error) `json:"-"`
	Timeout     time.Duration          `json:"timeout"`
	MaxMemoryMB int                    `json:"max_memory_mb"`
	AllowNetwork bool                  `json:"allow_network"`
	WhitelistIPs []string              `json:"whitelist_ips,omitempty"`
	BlacklistCmds []string             `json:"blacklist_cmds,omitempty"`
}

type AccessPolicy struct {
	DefaultDeny     bool                              `json:"default_deny"`
	Rules           []AccessRule                      `json:"rules"`
	RolePermissions map[string][]PermissionLevel      `json:"role_permissions"`
}

type AccessRule struct {
	ToolID     ToolID           `json:"tool_id"`
	Actions    []string         `json:"actions"`
	Allowed    bool             `json:"allowed"`
	Conditions []Condition      `json:"conditions,omitempty"`
}

type Condition struct {
	Field    string      `json:"field"`
	Operator string      `json:"operator"` // eq, neq, gt, lt, in, not_in, regex
	Value    interface{} `json:"value"`
}

type AuditLogger struct {
	entries []AuditEntry
	mu      sync.Mutex
}

type AuditEntry struct {
	Timestamp   time.Time              `json:"timestamp"`
	AgentID     AgentID                `json:"agent_id"`
	ToolID      ToolID                 `json:"tool_id"`
	Action      string                 `json:"action"`
	Params      map[string]interface{} `json:"params"`
	Result      string                 `json:"result"`
	Duration    time.Duration          `json:"duration"`
	Allowed     bool                   `json:"allowed"`
	RiskScore   float64                `json:"risk_score"`
	Violation   string                 `json:"violation,omitempty"`
}

// ============================================================
// 3. 权限控制系统
// ============================================================

type PermissionController struct {
	policies map[string]*AccessPolicy
	roles    map[string]*Role
	mu       sync.RWMutex
}

type Role struct {
	Name        string                     `json:"name"`
	Permissions map[string]PermissionLevel `json:"permissions"`
	Parents     []string                   `json:"parents,omitempty"`
	Constraints []Constraint               `json:"constraints,omitempty"`
}

type Constraint struct {
	Type        string      `json:"type"` // rate_limit, time_window, resource_limit
	MaxValue    int64       `json:"max_value"`
	Window      time.Duration `json:"window"`
	Current     int64       `json:"current"`
	ResetAt     time.Time   `json:"reset_at"`
}

func NewPermissionController() *PermissionController {
	return &PermissionController{
		policies: make(map[string]*AccessPolicy),
		roles:    make(map[string]*Role),
	}
}

func (pc *PermissionController) CheckPermission(agentCtx *AgentContext, toolID ToolID, action string) (bool, string) {
	pc.mu.RLock()
	defer pc.mu.RUnlock()

	// 1. 检查角色权限
	rolePerm, ok := agentCtx.Permissions[string(toolID)]
	if !ok {
		return false, "未授予该工具权限"
	}

	// 2. 检查所需权限级别
	tool, exists := pc.getTool(toolID)
	if !exists {
		return false, "工具不存在"
	}

	if rolePerm < tool.RequiredPerm {
		return false, fmt.Sprintf("权限不足: 需要 %v, 当前 %v", tool.RequiredPerm, rolePerm)
	}

	// 3. 检查约束条件
	for _, role := range pc.roles {
		for _, constraint := range role.Constraints {
			if !pc.checkConstraint(constraint) {
				return false, fmt.Sprintf("约束条件不满足: %s", constraint.Type)
			}
		}
	}

	return true, ""
}

func (pc *PermissionController) checkConstraint(c Constraint) bool {
	switch c.Type {
	case "rate_limit":
		if c.Current >= c.MaxValue {
			return false
		}
		if time.Now().After(c.ResetAt) {
			c.Current = 0
			c.ResetAt = time.Now().Add(c.Window)
		}
		return true
	case "time_window":
		now := time.Now()
		windowEnd := c.ResetAt
		return now.Before(windowEnd)
	default:
		return true
	}
}

// ============================================================
// 4. 工具调用验证器
// ============================================================

type ToolValidator struct {
	sanitizers []Sanitizer
	validators []ParamValidator
}

type Sanitizer func(value interface{}) (interface{}, error)
type ParamValidator func(name string, value interface{}) error

func NewToolValidator() *ToolValidator {
	v := &ToolValidator{}

	// 添加内置清洗器
	v.sanitizers = []Sanitizer{
		sanitizeCommandInjection,
		sanitizePathTraversal,
		sanitizeSQLInjection,
	}

	// 添加内置验证器
	v.validators = []ParamValidator{
		validateNoShellMetacharacters,
		validateFilePath,
		validateURL,
		validateEmail,
	}

	return v
}

func sanitizeCommandInjection(value interface{}) (interface{}, error) {
	str, ok := value.(string)
	if !ok {
		return value, nil
	}

	// 检查 shell 特殊字符
	dangerous := []string{";", "|", "&&", "||", "$(", "`", "${"}
	for _, d := range dangerous {
		if strings.Contains(str, d) {
			return nil, fmt.Errorf("检测到命令注入字符: %s", d)
		}
	}

	return str, nil
}

func sanitizePathTraversal(value interface{}) (interface{}, error) {
	str, ok := value.(string)
	if !ok {
		return value, nil
	}

	// 检查路径遍历
	if strings.Contains(str, "../") || strings.Contains(str, "..\\") {
		return nil, fmt.Errorf("检测到路径遍历攻击")
	}

	return str, nil
}

func sanitizeSQLInjection(value interface{}) (interface{}, error) {
	str, ok := value.(string)
	if !ok {
		return value, nil
	}

	// SQL 注入关键词检查
	sqlKeywords := []string{
		"(?i)DROP\\s+TABLE",
		"(?i)DELETE\\s+FROM",
		"(?i)INSERT\\s+INTO",
		"(?i)UPDATE\\s+SET",
		"(?i)EXEC\\s*\\(?",
		"(?i)xp_cmdshell",
		"(?i)UNION\\s+SELECT",
	}

	for _, pattern := range sqlKeywords {
		matched, _ := regexp.MatchString(pattern, str)
		if matched {
			return nil, fmt.Errorf("检测到 SQL 注入尝试")
		}
	}

	return str, nil
}

func validateNoShellMetacharacters(name string, value interface{}) error {
	str, ok := value.(string)
	if !ok {
		return nil
	}

	shellChars := ";&|`$(){}[]<>!#~"
	for _, c := range shellChars {
		if strings.ContainsRune(str, c) {
			return fmt.Errorf("参数 %s 包含非法字符: %c", name, c)
		}
	}

	return nil
}

func validateFilePath(name string, value interface{}) error {
	str, ok := value.(string)
	if !ok {
		return nil
	}

	// 只允许安全的路径模式
	safePattern := regexp.MustCompile(`^[a-zA-Z0-9_\-./]+$`)
	if !safePattern.MatchString(str) {
		return fmt.Errorf("参数 %s 路径格式不安全", name)
	}

	return nil
}

func validateURL(name string, value interface{}) error {
	str, ok := value.(string)
	if !ok {
		return nil
	}

	// URL 白名单检查
	urlPattern := regexp.MustCompile(`^https?://[a-zA-Z0-9][-a-zA-Z0-9.]*(:\d+)?(/[^\s]*)?$`)
	if !urlPattern.MatchString(str) {
		return fmt.Errorf("参数 %s URL 格式无效", name)
	}

	return nil
}

func validateEmail(name string, value interface{}) error {
	str, ok := value.(string)
	if !ok {
		return nil
	}

	emailPattern := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
	if !emailPattern.MatchString(str) {
		return fmt.Errorf("参数 %s 邮箱格式无效", name)
	}

	return nil
}

// ============================================================
// 5. 速率限制器
// ============================================================

type RateLimiter struct {
	buckets map[string]*TokenBucket
	mu      sync.Mutex
}

type TokenBucket struct {
	Capacity   int64
	Tokens     int64
	RefillRate float64
	LastRefill time.Time
}

func NewRateLimiter() *RateLimiter {
	return &RateLimiter{
		buckets: make(map[string]*TokenBucket),
	}
}

func (rl *RateLimiter) Allow(key string, tokens int64) bool {
	rl.mu.Lock()
	defer rl.mu.Unlock()

	bucket, exists := rl.buckets[key]
	if !exists {
		bucket = &TokenBucket{
			Capacity:   100,
			Tokens:     100,
			RefillRate: 10.0,
			LastRefill: time.Now(),
		}
		rl.buckets[key] = bucket
	}

	// Refill tokens
	elapsed := time.Since(bucket.LastRefill).Seconds()
	bucket.Tokens = int64(math.Min(float64(bucket.Capacity), float64(bucket.Tokens)+elapsed*bucket.RefillRate))
	bucket.LastRefill = time.Now()

	if bucket.Tokens >= tokens {
		bucket.Tokens -= tokens
		return true
	}

	return false
}

// ============================================================
// 6. Agent 安全管理器
// ============================================================

type AgentSecurityManager struct {
	sandbox        *ToolSandbox
	permController *PermissionController
	validator      *ToolValidator
	rateLimiter    *RateLimiter
	auditLogger    *AuditLogger
	sessions       map[SessionID]*AgentContext
	mu             sync.RWMutex
}

func NewAgentSecurityManager() *AgentSecurityManager {
	mgr := &AgentSecurityManager{
		sandbox:        &ToolSandbox{tools: make(map[ToolID]*RegisteredTool)},
		permController: NewPermissionController(),
		validator:      NewToolValidator(),
		rateLimiter:    NewRateLimiter(),
		auditLogger:    &AuditLogger{},
		sessions:       make(map[SessionID]*AgentContext),
	}

	mgr.registerDefaultTools()
	mgr.setupDefaultRoles()

	return mgr
}

func (mgr *AgentSecurityManager) registerDefaultTools() {
	// 注册文件读取工具
	mgr.sandbox.tools["file_read"] = &RegisteredTool{
		ID:              "file_read",
		Name:            "文件读取",
		Description:     "读取指定文件内容",
		Version:         "1.0.0",
		RequiredPerm:    PermissionRestricted,
		Timeout:         30 * time.Second,
		MaxMemoryMB:     50,
		AllowNetwork:    false,
		BlacklistCmds:   []string{"rm", "dd", "mkfs", ":(){ :|:& };:"},
		Validator: func(params map[string]interface{}) error {
			path, ok := params["path"].(string)
			if !ok {
				return fmt.Errorf("缺少 path 参数")
			}

			// 路径安全检查
			if strings.Contains(path, "..") {
				return fmt.Errorf("不允许路径遍历")
			}

			// 只允许读取特定目录
			allowedPrefixes := []string{"/data/", "/tmp/", "/home/"}
			allowed := false
			for _, prefix := range allowedPrefixes {
				if strings.HasPrefix(path, prefix) {
					allowed = true
					break
				}
			}
			if !allowed {
				return fmt.Errorf("不允许读取该路径")
			}

			return nil
		},
		Executor: func(ctx context.Context, params map[string]interface{}) (interface{}, error) {
			// 实际文件读取逻辑
			return "文件内容", nil
		},
	}

	// 注册网络请求工具
	mgr.sandbox.tools["http_request"] = &RegisteredTool{
		ID:              "http_request",
		Name:            "HTTP 请求",
		Description:     "发送 HTTP 请求获取远程资源",
		Version:         "1.0.0",
		RequiredPerm:    PermissionStandard,
		Timeout:         60 * time.Second,
		MaxMemoryMB:     200,
		AllowNetwork:    true,
		WhitelistIPs:    []string{"0.0.0.0/0"},
		Validator: func(params map[string]interface{}) error {
			url, ok := params["url"].(string)
			if !ok {
				return fmt.Errorf("缺少 url 参数")
			}

			// URL 安全检查
			if !strings.HasPrefix(url, "https://") {
				return fmt.Errorf("只允许 HTTPS 协议")
			}

			// 域名黑名单
			blacklistDomains := []string{"internal.company.com", "localhost", "127.0.0.1"}
			for _, domain := range blacklistDomains {
				if strings.Contains(url, domain) {
					return fmt.Errorf("不允许访问内网地址")
				}
			}

			return nil
		},
		Executor: func(ctx context.Context, params map[string]interface{}) (interface{}, error) {
			// 实际 HTTP 请求逻辑
			return map[string]interface{}{
				"status_code": 200,
				"body":        "响应内容",
			}, nil
		},
	}

	// 注册代码执行工具
	mgr.sandbox.tools["code_exec"] = &RegisteredTool{
		ID:              "code_exec",
		Name:            "代码执行",
		Description:     "在沙箱环境中执行代码",
		Version:         "1.0.0",
		RequiredPerm:    PermissionElevated,
		Timeout:         120 * time.Second,
		MaxMemoryMB:     500,
		AllowNetwork:    false,
		BlacklistCmds:   []string{"sudo", "su", "chmod", "chown", "mount", "umount"},
		Validator: func(params map[string]interface{}) error {
			code, ok := params["code"].(string)
			if !ok {
				return fmt.Errorf("缺少 code 参数")
			}

			language, ok := params["language"].(string)
			if !ok {
				language = "python"
			}

			// 语言白名单
			allowedLanguages := map[string]bool{
				"python": true,
				"go":     true,
				"bash":   true,
				"node":   true,
			}

			if !allowedLanguages[language] {
				return fmt.Errorf("不允许的语言: %s", language)
			}

			// 代码安全检查
			dangerousPatterns := []string{
				"os.system", "subprocess.call", "exec(", "eval(",
				"__import__", "open(", "file(",
			}

			for _, pattern := range dangerousPatterns {
				if strings.Contains(code, pattern) {
					return fmt.Errorf("检测到危险函数调用: %s", pattern)
				}
			}

			return nil
		},
		Executor: func(ctx context.Context, params map[string]interface{}) (interface{}, error) {
			// 实际代码执行逻辑(在沙箱中)
			return "执行结果", nil
		},
	}
}

func (mgr *AgentSecurityManager) setupDefaultRoles() {
	// 定义角色层级
	roles := map[string]*Role{
		"guest": {
			Name: "访客",
			Permissions: map[string]PermissionLevel{
				"file_read":     PermissionReadOnly,
				"search":        PermissionReadOnly,
			},
			Constraints: []Constraint{
				{Type: "rate_limit", MaxValue: 10, Window: time.Minute},
			},
		},
		"user": {
			Name: "普通用户",
			Permissions: map[string]PermissionLevel{
				"file_read":     PermissionRestricted,
				"http_request": PermissionStandard,
				"search":        PermissionReadOnly,
			},
			Constraints: []Constraint{
				{Type: "rate_limit", MaxValue: 100, Window: time.Minute},
			},
		},
		"developer": {
			Name: "开发者",
			Permissions: map[string]PermissionLevel{
				"file_read":     PermissionStandard,
				"http_request": PermissionStandard,
				"code_exec":    PermissionElevated,
				"db_query":     PermissionStandard,
			},
			Constraints: []Constraint{
				{Type: "rate_limit", MaxValue: 500, Window: time.Minute},
			},
		},
		"admin": {
			Name: "管理员",
			Permissions: map[string]PermissionLevel{
				"file_read":     PermissionAdmin,
				"http_request": PermissionAdmin,
				"code_exec":    PermissionAdmin,
				"db_query":     PermissionAdmin,
				"system_config": PermissionAdmin,
			},
			Constraints: []Constraint{
				{Type: "rate_limit", MaxValue: 1000, Window: time.Minute},
			},
		},
	}

	for id, role := range roles {
		mgr.permController.roles[id] = role
	}
}

// ============================================================
// 7. Agent 工具调用流程
// ============================================================

func (mgr *AgentSecurityManager) ExecuteTool(
	ctx context.Context,
	agentCtx *AgentContext,
	toolID ToolID,
	action string,
	params map[string]interface{},
) (interface{}, error) {

	startTime := time.Now()

	// 1. 权限检查
	allowed, reason := mgr.permController.CheckPermission(agentCtx, toolID, action)
	if !allowed {
		mgr.auditLogger.Log(AuditEntry{
			Timestamp: startTime,
			AgentID:   agentCtx.AgentID,
			ToolID:    toolID,
			Action:    action,
			Params:    params,
			Allowed:   false,
			Violation: reason,
			RiskScore: 1.0,
		})
		return nil, fmt.Errorf("权限拒绝: %s", reason)
	}

	// 2. 速率限制检查
	rateKey := fmt.Sprintf("%s:%s", agentCtx.AgentID, toolID)
	if !mgr.rateLimiter.Allow(rateKey, 1) {
		mgr.auditLogger.Log(AuditEntry{
			Timestamp: startTime,
			AgentID:   agentCtx.AgentID,
			ToolID:    toolID,
			Action:    action,
			Params:    params,
			Allowed:   false,
			Violation: "速率限制",
			RiskScore: 0.8,
		})
		return nil, fmt.Errorf("请求过于频繁,请稍后再试")
	}

	// 3. 参数验证
	tool, exists := mgr.sandbox.tools[toolID]
	if !exists {
		return nil, fmt.Errorf("工具不存在: %s", toolID)
	}

	if tool.Validator != nil {
		if err := tool.Validator(params); err != nil {
			mgr.auditLogger.Log(AuditEntry{
				Timestamp: startTime,
				AgentID:   agentCtx.AgentID,
				ToolID:    toolID,
				Action:    action,
				Params:    params,
				Allowed:   false,
				Violation: fmt.Sprintf("参数验证失败: %s", err.Error()),
				RiskScore: 0.6,
			})
			return nil, fmt.Errorf("参数验证失败: %s", err.Error())
		}
	}

	// 4. 额外清洗
	for name, value := range params {
		sanitized, err := mgr.validator.SanitizeParam(name, value)
		if err != nil {
			return nil, fmt.Errorf("参数清洗失败 [%s]: %s", name, err.Error())
		}
		params[name] = sanitized
	}

	// 5. 执行工具(带超时)
	type result struct {
		data interface{}
		err  error
	}

	resultCh := make(chan result, 1)
	go func() {
		data, err := tool.Executor(ctx, params)
		resultCh <- result{data, err}
	}()

	select {
	case res := <-resultCh:
		duration := time.Since(startTime)

		// 记录审计日志
		entry := AuditEntry{
			Timestamp: startTime,
			AgentID:   agentCtx.AgentID,
			ToolID:    toolID,
			Action:    action,
			Params:    params,
			Duration:  duration,
			Allowed:   true,
			RiskScore: 0.0,
		}

		if res.err != nil {
			entry.Result = fmt.Sprintf("error: %s", res.err.Error())
			entry.RiskScore = 0.3
		} else {
			resultJSON, _ := json.Marshal(res.data)
			entry.Result = string(resultJSON)
		}

		mgr.auditLogger.Log(entry)

		// 更新 Agent 上下文
		mgr.updateAgentContext(agentCtx, toolID, action, params, entry)

		return res.data, res.err

	case <-time.After(tool.Timeout):
		mgr.auditLogger.Log(AuditEntry{
			Timestamp: startTime,
			AgentID:   agentCtx.AgentID,
			ToolID:    toolID,
			Action:    action,
			Params:    params,
			Allowed:   false,
			Violation: "执行超时",
			RiskScore: 0.5,
		})
		return nil, fmt.Errorf("工具执行超时 (%v)", tool.Timeout)
	}
}

func (mgr *AgentSecurityManager) updateAgentContext(
	agentCtx *AgentContext,
	toolID ToolID,
	action string,
	params map[string]interface{},
	entry AuditEntry,
) {
	mgr.mu.Lock()
	defer mgr.mu.Unlock()

	record := ToolCallRecord{
		ToolID:    toolID,
		Action:    action,
		Params:    params,
		Timestamp: entry.Timestamp,
		Duration:  entry.Duration,
		Allowed:   entry.Allowed,
		Reason:    entry.Violation,
	}

	agentCtx.ToolCalls = append(agentCtx.ToolCalls, record)
}

// ============================================================
// 8. 辅助方法
// ============================================================

func (v *ToolValidator) SanitizeParam(name string, value interface{}) (interface{}, error) {
	current := value
	for _, sanitizer := range v.sanitizers {
		var err error
		current, err = sanitizer(current)
		if err != nil {
			return nil, err
		}
	}
	return current, nil
}

func (pc *PermissionController) getTool(toolID ToolID) (*RegisteredTool, bool) {
	// 简化实现,实际应从全局工具注册表获取
	return &RegisteredTool{RequiredPerm: PermissionStandard}, true
}

func (al *AuditLogger) Log(entry AuditEntry) {
	al.mu.Lock()
	defer al.mu.Unlock()
	al.entries = append(al.entries, entry)

	// 高风险事件实时告警
	if entry.RiskScore >= 0.8 {
		log.Printf("🚨 高风险事件: Agent=%s Tool=%s Action=%s Risk=%.2f Violation=%s",
			entry.AgentID, entry.ToolID, entry.Action, entry.RiskScore, entry.Violation)
	}
}

// ============================================================
// 9. 主程序演示
// ============================================================

func main() {
	fmt.Println("========== 第6讲:Agent 安全 ==========\n")

	// 1. 创建安全管理器
	mgr := NewAgentSecurityManager()

	// 2. 创建 Agent 上下文
	agentCtx := &AgentContext{
		AgentID:   "agent-001",
		SessionID: "session-abc123",
		UserID:    "user-001",
		Permissions: map[string]PermissionLevel{
			"file_read":     PermissionRestricted,
			"http_request": PermissionStandard,
			"code_exec":    PermissionElevated,
		},
		StartTime: time.Now(),
		ExpiresAt: time.Now().Add(30 * time.Minute),
	}

	// 3. 测试各种工具调用
	testCases := []struct {
		name   string
		toolID ToolID
		action string
		params map[string]interface{}
	}{
		{
			name:   "✅ 合法文件读取",
			toolID: "file_read",
			action: "read",
			params: map[string]interface{}{
				"path": "/data/config.json",
			},
		},
		{
			name:   "❌ 路径遍历攻击",
			toolID: "file_read",
			action: "read",
			params: map[string]interface{}{
				"path": "../../etc/passwd",
			},
		},
		{
			name:   "✅ 合法 HTTP 请求",
			toolID: "http_request",
			action: "get",
			params: map[string]interface{}{
				"url": "https://api.example.com/data",
			},
		},
		{
			name:   "❌ SSRF 攻击",
			toolID: "http_request",
			action: "get",
			params: map[string]interface{}{
				"url": "http://localhost:8080/admin",
			},
		},
		{
			name:   "❌ 命令注入",
			toolID: "code_exec",
			action: "execute",
			params: map[string]interface{}{
				"code":     "print('hello'); os.system('rm -rf /')",
				"language": "python",
			},
		},
		{
			name:   "✅ 合法代码执行",
			toolID: "code_exec",
			action: "execute",
			params: map[string]interface{}{
				"code":     "print('Hello, World!')",
				"language": "python",
			},
		},
	}

	ctx := context.Background()

	for _, tc := range testCases {
		fmt.Printf("🔧 %s\n", tc.name)
		fmt.Printf("   工具: %s | 动作: %s\n", tc.toolID, tc.action)
		fmt.Printf("   参数: %v\n", tc.params)

		result, err := mgr.ExecuteTool(ctx, agentCtx, tc.toolID, tc.action, tc.params)
		if err != nil {
			fmt.Printf("   ❌ 失败: %s\n", err.Error())
		} else {
			fmt.Printf("   ✅ 成功: %v\n", result)
		}
		fmt.Println()
	}

	// 4. 输出审计日志摘要
	fmt.Println("📋 审计日志摘要:")
	fmt.Printf("   总调用次数: %d\n", len(mgr.auditLogger.entries))
	
	blockedCount := 0
	for _, entry := range mgr.auditLogger.entries {
		if !entry.Allowed {
			blockedCount++
		}
	}
	fmt.Printf("   拦截次数: %d\n", blockedCount)
	fmt.Printf("   成功率: %.1f%%\n", float64(len(mgr.auditLogger.entries)-blockedCount)/float64(len(mgr.auditLogger.entries))*100)
}

三、Agent 安全架构图

复制代码
┌─────────────────────────────────────────────────────────────┐
│                     Agent 安全架构                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌──────────┐    ┌──────────┐    ┌──────────┐              │
│  │ 用户输入  │───▶│ Prompt   │───▶│ 意图识别  │              │
│  └──────────┘    │ 过滤器    │    └────┬─────┘              │
│                  └──────────┘         │                    │
│                                       ▼                    │
│  ┌──────────────────────────────────────────────────┐      │
│  │              Agent 决策引擎                        │      │
│  │  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐│      │
│  │  │ 权限检查  │ │ 参数验证  │ │ 速率限制  │ │ 上下文   ││      │
│  │  └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘│      │
│  └───────┼───────────┼───────────┼───────────┼──────┘      │
│          ▼           ▼           ▼           ▼              │
│  ┌──────────────────────────────────────────────────┐      │
│  │              工具沙箱                               │      │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐          │      │
│  │  │ 文件系统   │ │ 网络请求  │ │ 代码执行  │          │      │
│  │  │ (受限)    │ │ (白名单)  │ │ (沙箱)   │          │      │
│  │  └──────────┘ └──────────┘ └──────────┘          │      │
│  └──────────────────────────────────────────────────┘      │
│          │                                                   │
│          ▼                                                   │
│  ┌──────────────────────────────────────────────────┐      │
│  │              输出安全                               │      │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐          │      │
│  │  │ 内容过滤   │ │ 结果校验  │ │ 审计日志  │          │      │
│  │  └──────────┘ └──────────┘ └──────────┘          │      │
│  └──────────────────────────────────────────────────┘      │
│          │                                                   │
│          ▼                                                   │
│  ┌──────────────────────────────────────────────────┐      │
│  │              输出到用户                             │      │
│  └──────────────────────────────────────────────────┘      │
└─────────────────────────────────────────────────────────────┘

四、Agent 安全最佳实践

1. 权限最小化原则

复制代码
角色             文件读取    网络请求    代码执行    数据库
─────────────────────────────────────────────────────────
访客(guset)       ReadOnly    ❌         ❌        ❌
用户(user)        Restricted  Standard   ❌        ❌
开发者(dev)       Standard    Standard   Elevated  Standard
管理员(admin)     Admin       Admin      Admin     Admin

2. 工具调用安全清单

检查项 说明 严重程度
权限验证 每次调用前检查角色权限 必须
参数清洗 防止注入攻击 必须
速率限制 防止资源耗尽 必须
超时控制 防止长时间阻塞 必须
结果过滤 防止敏感信息泄露 必须
审计日志 完整记录调用链 必须
上下文隔离 不同会话数据隔离 必须
内存限制 防止 OOM 建议

3. 供应链安全

复制代码
# agent-security.yaml
supply_chain:
  # 工具签名验证
  signature_verification: true
  
  # 依赖版本锁定
  dependency_pinning:
    go_modules: "go.sum"
    python_packages: "requirements.txt.lock"
    
  # 安全扫描
  vulnerability_scanning:
    frequency: "daily"
    scanner: "trivy"
    severity_threshold: "HIGH"
    
  # 来源白名单
  source_whitelist:
    registries:
      - "docker.io/*"
      - "gcr.io/google-containers/*"
    block_patterns:
      - "*/experimental/*"
      - "*/unstable/*"

五、生产部署配置

复制代码
# agent-production-config.yaml
agent_security:
  session:
    timeout: 30m
    max_concurrent_tools: 5
    
  tools:
    file_read:
      enabled: true
      allowed_paths:
        - "/data/*"
        - "/tmp/agent-*"
      block_paths:
        - "/etc/*"
        - "/proc/*"
      max_file_size: "10MB"
      
    http_request:
      enabled: true
      allowed_domains:
        - "*.example.com"
        - "api.github.com"
      block_domains:
        - "*.internal"
        - "169.254.*"
      timeout: 30s
      
    code_exec:
      enabled: true
      sandbox_type: "container"
      resource_limits:
        cpu: "1 core"
        memory: "512MB"
        disk: "1GB"
      network: false
      timeout: 300s
      
  monitoring:
    alert_on:
      - "blocked_access"
      - "rate_limit_exceeded"
      - "parameter_validation_failed"
    metrics:
      - "tool_call_count"
      - "average_latency"
      - "error_rate"
      - "block_rate"

六、关键要点

  1. 每个工具调用都必须是受控的 --- 权限、参数、速率三重检查
  2. 沙箱隔离是最后防线 --- 即使验证通过,也要限制执行环境
  3. 审计日志不可篡改 --- 完整的调用链追溯能力
  4. 供应链安全不容忽视 --- 工具的引入本身就是风险点
  5. 最小权限原则贯穿始终 --- 从角色定义到每次调用

🧰 开发之余的小工具推荐

处理 JSON 格式化、JWT 解析、Base64 编解码、Crontab 表达式计算这类日常开发需求,我习惯用 zz365.top 这个纯前端工具箱。所有计算都在浏览器本地完成,文件不会上传到任何服务器,关闭页面即清除。免费、无需登录、没有广告,适合作为开发者的常驻工具页。


下一讲:第7讲:模型安全与对抗攻击​ --- 模型窃取、对抗样本、后门攻击、联邦学习安全、模型水印。

相关推荐
XLYcmy1 小时前
AI 时代,MOM(制造运营管理系统)该如何演进? 上
ai·llm·agent·模型·mom·harness·工业系统
浩瀚地学2 小时前
deepagents学习打卡day08
经验分享·笔记·python·学习·agent
無a伟2 小时前
彻底搞懂ToolCalling、MCP,Skills的核心区别,能力上的层层封装
大数据·agent·mcp·toolcalling·skills
七夜zippoe2 小时前
RAG 2.0:从向量检索到 Agent 自主知识治理的进化路径
ai·agent·向量检索·rag 2.0·自主知识治理
凉凉的知识库3 小时前
Agent 如何拥有长期记忆:六个主流项目的设计思路对比
开源·llm·agent
AI-Frontiers5 小时前
现代智能体系统的自主迭代能力研究综述
agent
Ticnix5 小时前
RAG 烂大街?烂大街的只是那条流水线——真正的分水岭在这五处
后端·python·agent
Ticnix6 小时前
RAG 检索不准,九成的锅不在向量——不同文件,就该有不同的入库方案
后端·python·agent
吴佳浩6 小时前
Agent 安全红线:越狱防御、间接注入与数据防泄漏实战
人工智能·agent·ai编程