Skills 在 Shell 环境中的安全执行
AI 大模型开发

Skills 在 Shell 环境中的安全执行

JACIN6 分钟阅读
AI 摘要

这篇笔记聚焦 Skills 挂载到 Shell 环境后的执行安全,核心判断是不能只依赖模型自觉遵守规则,而要由后端对命令生成、执行环境和输出结果形成闭环控制。内容按四层防护展开:先在 SKILL.md 中声明允许读取、创建或修改的范围,并明确禁止删除系统文件、访问敏感目录、执行网络命令等高风险行为;随后通过命令白名单和正则黑名单,在执行前拦截 rm -rf、sudo、chmod 777、写入 /etc 等危险模式。执行阶段建议放入 Docker 沙盒,限制镜像、内存、CPU、超时时间,关闭网络,并将 /data 以只读方式挂载,降低命令越权和资源滥用的影响面。最后一层是结果过滤与审计,记录执行命令和输出长度,同时对 password、token、api_key 等敏感字段脱敏,并截断过长输出,避免把风险从执行环节转移到返回内容。它适合正在把 AI Skills、Agent 工具调用或自动化脚本接入后端的开发者,用来建立一套可落地的最小安全框架。需要注意的是,提示词约束只是第一道软边界,真正的安全性来自白名单校验、隔离运行和输出治理的组合,而不是让模型“更聪明”。

Skills 在 Shell 环境中的安全执行#

当 skills 挂在 shell 环境里时,关键不是"让模型更聪明",而是"让后端把执行过程管住"。

四层安全控制模型#

第一层:提示词约束#

在 SKILL.md 中明确告诉模型允许和禁止的操作:

markdown
---
name: file-operations
description: 安全的文件操作 skill
---

## 允许的操作
- 读取 /data 目录下的文件
- 创建临时文件
- 修改日志文件

## 禁止的操作
- 删除系统文件
- 修改配置文件
- 执行网络命令
- 访问 /etc 或 /root 目录

## 命令格式
所有命令必须遵循以下格式:
\`\`\`
operation: read|write|create
path: /data/...
content: ...
\`\`\`

第二层:命令白名单和执行前校验#

python
ALLOWED_COMMANDS = {
    'read': ['cat', 'head', 'tail'],
    'write': ['echo', 'tee'],
    'execute': ['python', 'node'],
}

FORBIDDEN_PATTERNS = [
    r'rm\s+-rf',
    r'sudo',
    r'chmod\s+777',
    r'>\s*/etc',
]

def validate_command(command: str) -> bool:
    """验证命令是否安全"""
    # 检查禁止模式
    for pattern in FORBIDDEN_PATTERNS:
        if re.search(pattern, command):
            return False

    # 检查命令白名单
    cmd_name = command.split()[0]
    for allowed_cmds in ALLOWED_COMMANDS.values():
        if cmd_name in allowed_cmds:
            return True

    return False

第三层:沙盒隔离#

python
import docker
import subprocess

def execute_in_sandbox(command: str, timeout: int = 30) -> str:
    """在 Docker 容器中执行命令"""
    client = docker.from_env()

    container = client.containers.run(
        "python:3.11-slim",
        command=command,
        detach=True,
        mem_limit="512m",
        memswap_limit="512m",
        cpus=1.0,
        network_disabled=True,
        volumes={
            '/data': {'bind': '/data', 'mode': 'ro'}
        },
        timeout=timeout
    )

    result = container.wait()
    logs = container.logs().decode()
    container.remove()

    return logs

第四层:执行后审计和结果过滤#

python
import logging
import re

logger = logging.getLogger(__name__)

def filter_and_audit_result(result: str, command: str) -> str:
    """过滤敏感信息并记录审计日志"""

    # 审计日志
    logger.info(f"Command executed: {command}")
    logger.info(f"Result length: {len(result)}")

    # 脱敏敏感信息
    sensitive_patterns = [
        (r'password\s*=\s*[^\s]+', 'password=***'),
        (r'token\s*=\s*[^\s]+', 'token=***'),
        (r'api[_-]?key\s*=\s*[^\s]+', 'api_key=***'),
    ]

    filtered_result = result
    for pattern, replacement in sensitive_patterns:
        filtered_result = re.sub(pattern, replacement, filtered_result, flags=re.IGNORECASE)

    # 截断过长输出
    max_length = 10000
    if len(filtered_result) > max_length:
        filtered_result = filtered_result[:max_length] + "\n... (output truncated)"

    return filtered_result

评论

还没有评论,来发第一个吧