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

Skills 在 Shell 环境中的安全执行

JACIN6 分钟阅读

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

评论

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