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