Claude Skills 安全最佳实践
当 Skills 执行真实代码时,安全性至关重要。遵循这些实践来保护你的系统。
关键安全原则
1. 输入验证
始终验证和清理输入:
python1def process_file(filepath): 2 # 验证文件存在 3 if not os.path.exists(filepath): 4 raise ValueError("File not found") 5 6 # 检查文件类型 7 allowed_extensions = ['.pdf', '.docx', '.txt'] 8 if not any(filepath.endswith(ext) for ext in allowed_extensions): 9 raise ValueError("Invalid file type") 10 11 # 检查文件大小 12 if os.path.getsize(filepath) > 10 * 1024 * 1024: # 10MB 13 raise ValueError("File too large")1def process_file(filepath): 2 # 验证文件存在 3 if not os.path.exists(filepath): 4 raise ValueError("File not found") 5 6 # 检查文件类型 7 allowed_extensions = ['.pdf', '.docx', '.txt'] 8 if not any(filepath.endswith(ext) for ext in allowed_extensions): 9 raise ValueError("Invalid file type") 10 11 # 检查文件大小 12 if os.path.getsize(filepath) > 10 * 1024 * 1024: # 10MB 13 raise ValueError("File too large")
2. 沙箱
在隔离环境中运行不受信任的代码:
python1import subprocess 2 3def run_sandboxed(script_path): 4 result = subprocess.run( 5 ['docker', 'run', '--rm', '-v', f'{script_path}:/app', 'python:3.9', 'python', '/app/script.py'], 6 capture_output=True, 7 timeout=30 8 ) 9 return result.stdout1import subprocess 2 3def run_sandboxed(script_path): 4 result = subprocess.run( 5 ['docker', 'run', '--rm', '-v', f'{script_path}:/app', 'python:3.9', 'python', '/app/script.py'], 6 capture_output=True, 7 timeout=30 8 ) 9 return result.stdout
3. 秘密管理
永不硬编码敏感数据:
python1import os 2 3# ✅ 好: 使用环境变量 4API_KEY = os.getenv('API_KEY') 5 6# ❌ 差: 硬编码秘密 7# API_KEY = "sk-1234567890abcdef"1import os 2 3# ✅ 好: 使用环境变量 4API_KEY = os.getenv('API_KEY') 5 6# ❌ 差: 硬编码秘密 7# API_KEY = "sk-1234567890abcdef"
4. 最小权限原则
请求最少权限:
markdown## 所需权限 - 文件读取: /data/input/ - 文件写入: /data/output/ - 网络: 无## 所需权限 - 文件读取: /data/input/ - 文件写入: /data/output/ - 网络: 无
5. 代码审查
部署前审核 Skills:
bash# 检查危险模式 grep -r "eval(" skill/ grep -r "exec(" skill/ grep -r "subprocess.call" skill/# 检查危险模式 grep -r "eval(" skill/ grep -r "exec(" skill/ grep -r "subprocess.call" skill/
常见漏洞
路径遍历
python1# ❌ 有漏洞 2def read_file(filename): 3 return open(filename).read() 4# 攻击: read_file("../../etc/passwd") 5 6# ✅ 安全 7import os 8def read_file(filename): 9 base_dir = "/safe/directory" 10 filepath = os.path.join(base_dir, filename) 11 if not filepath.startswith(base_dir): 12 raise ValueError("Invalid path") 13 return open(filepath).read()1# ❌ 有漏洞 2def read_file(filename): 3 return open(filename).read() 4# 攻击: read_file("../../etc/passwd") 5 6# ✅ 安全 7import os 8def read_file(filename): 9 base_dir = "/safe/directory" 10 filepath = os.path.join(base_dir, filename) 11 if not filepath.startswith(base_dir): 12 raise ValueError("Invalid path") 13 return open(filepath).read()
命令注入
python# ❌ 有漏洞 os.system(f"convert {filename} output.pdf") # ✅ 安全 subprocess.run(['convert', filename, 'output.pdf'], check=True)# ❌ 有漏洞 os.system(f"convert {filename} output.pdf") # ✅ 安全 subprocess.run(['convert', filename, 'output.pdf'], check=True)
任意代码执行
python1# ❌ 危险 2eval(user_input) 3exec(user_code) 4 5# ✅ 使用安全替代方案 6import ast 7ast.literal_eval(user_input) # 仅用于字面量1# ❌ 危险 2eval(user_input) 3exec(user_code) 4 5# ✅ 使用安全替代方案 6import ast 7ast.literal_eval(user_input) # 仅用于字面量
安全检查清单
- [ ] 所有输入已验证
- [ ] 文件路径已清理
- [ ] 命令使用带列表参数的 subprocess
- [ ] 无硬编码秘密
- [ ] 所有操作有超时
- [ ] 错误消息不泄漏敏感信息
- [ ] 来自可信来源的依赖
- [ ] 定期安全审计
监控
记录安全相关事件:
pythonimport logging logging.info(f"Skill executed: {skill_name} by {user_id}") logging.warning(f"Invalid input attempt: {input_data}") logging.error(f"Security violation: {error_details}")import logging logging.info(f"Skill executed: {skill_name} by {user_id}") logging.warning(f"Invalid input attempt: {input_data}") logging.error(f"Security violation: {error_details}")
资源
阅读时间:4分钟
作者: ClaudeSkills 团队