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
评论
还没有评论,来发第一个吧
