Goose 安全加固
Goose 是一款强大的分析型数据库引擎。它可以读写文件、访问网络、加载扩展并使用系统资源。 和任何强大工具一样,在处理敏感数据或共享环境时,这些能力都需要合适的安全配置。
本页介绍 Goose 的安全模型与安全相关配置。正确配置取决于你的使用场景、运行环境和威胁模型。 如果你计划在应用中嵌入 Goose,也请参阅 “Embedding Goose” 页面。
不可信输入
不可信 SQL 输入
警告:在 Goose 中应像对待 Bash 或 Python 代码一样对待 SQL。不要在缺乏适当沙箱隔离的情况下执行来自不可信来源的 SQL。
Goose 执行 SQL 时使用运行该进程用户的完整权限,这与 shell 或脚本解释器(如 bash、Python)类似。 正如你不会在无沙箱环境下运行不可信 shell 脚本或 Python 程序,对 Goose SQL 也应同样谨慎。
如果你的应用必须执行不可信来源 SQL,请在运行时增加额外防护,例如:
- 在隔离容器中运行 Goose(例如启用能力限制的 Docker)
- 使用最小权限虚拟机或独立进程
- 启用操作系统级沙箱
- 使用网络隔离防止数据外泄
- 在应用层实现严格查询超时
本页配置提供的是纵深防御(defense-in-depth),可限制部分能力,但不能替代真正的沙箱隔离。还需注意,沙箱不仅用于安全,也用于防范拒绝服务(DoS):恶意输入很容易导致 Goose 过度消耗内存、磁盘、CPU 或网络资源。
不可信非 SQL 输入
警告:即便是非 SQL 输入,也可能在 Goose 中产生意外后果。构建安全敏感应用时,请务必充分理解向 Goose 输入不可信数据的影响。
除 SQL 外,Goose 还提供多种非 SQL API 与数据库交互。例如 Python 中的 relational API 支持以编程方式构建查询。
这些 API 接受文件路径、表名、列名、过滤表达式等用户输入。虽然它们不直接执行原始 SQL 字符串,但仍会触发 Goose 的文件读取、网络访问与系统资源使用行为。
非 SQL API 的典型风险点:
- 文件路径:
goose.read_csv(path)、goose.read_parquet(path)等函数接受文件路径。若路径可被攻击者控制,可能读取敏感文件(如/etc/passwd)或访问远程 URL。 - 表名与列名: 虽通常是标识符而非可执行代码,但未经清洗的输入仍可能导致异常行为或信息泄露。
- 过滤表达式: 部分 API 接受会被编译为 Goose 表达式的过滤条件,其中常支持包含任意 SQL 的子查询。应与 SQL 同等谨慎处理。
建议:
- 将用户输入传给 Goose API 前,先进行校验与清洗。
- 接收不可信来源输入时,采用与不可信 SQL 相同的沙箱原则。
- 仔细阅读所用函数文档,确认在你的场景中它们是否可安全处理不可信输入。
扩展
Goose 提供灵活的扩展机制,可增加新文件格式、函数、远程文件系统访问等能力。扩展以 Goose 进程同等权限运行,因此在安全敏感环境中必须谨慎评估。
自动加载
当某些 SQL 语句需要时,Goose 可自动加载核心扩展。若你希望完全控制可加载扩展,可禁用自动加载:
SET autoload_known_extensions = false;
SET autoinstall_known_extensions = false;
Core 与 Community 扩展
Goose 扩展分为两类:
- Core extensions: 由 Goose 团队维护并提供完整支持,如
parquet、json、httpfs。 - Community extensions: 由第三方贡献,通过
INSTALL extension_name FROM community安装。此类扩展不由 Goose 团队维护,请仅从可信来源安装。
要彻底禁用社区扩展:
SET allow_community_extensions = false;
漏洞报告
若你发现潜在漏洞,请通过 GitHub 保密提交安全报告。
限制 Goose 能力的设置
本节配置可为 Goose 部署提供额外加固。但在所有配置下都不应将其视为完整安全机制。 这些设置属于纵深防御措施,旨在降低潜在安全问题影响,但无法覆盖所有攻击向量,尤其在执行不可信 SQL 时。 处理不可信输入时,请按“不可信 SQL 输入”所述,将这些设置与操作系统或容器级沙箱结合使用。
安全模式(CLI)
Goose CLI 客户端支持“安全模式”,可阻止 Goose 访问数据库文件以外的外部文件。 可通过命令行参数或 dot command 启用:
goose -safe ...
.safe_mode
限制文件访问
Goose 可通过 CSV 解析器的 read_csv 函数列目录与读取任意文件,也可通过 read_text 函数读取文本。
因此它可以访问本地文件系统,例如:
SELECT *
FROM read_csv('/etc/passwd', sep = ':');
禁用文件访问
文件访问可通过两种方式禁用。第一种是禁用特定文件系统。例如:
SET disabled_filesystems = 'LocalFileSystem';
第二种是将 enable_external_access 选项设为 false,彻底禁用外部访问。
SET enable_external_access = false;
此设置意味着:
ATTACH无法附加文件中的数据库。COPY无法读写文件。read_csv、read_parquet、read_json等函数无法从外部源读取。
allowed_directories 与 allowed_paths 选项
你可以分别使用 allowed_directories 与 allowed_paths 限制 Goose 对目录或文件的访问。
这两个选项支持对文件系统进行细粒度访问控制。
例如,可将 Goose 限制为只使用 /tmp 目录。
SET allowed_directories = ['/tmp'];
SET enable_external_access = false;
FROM read_csv('test.csv');
应用该设置后,Goose 将拒绝读取当前工作目录中的文件:
Permission Error:
Cannot access file "test.csv" - file system operations are disabled by configuration
锁定配置
出于安全考虑,安全相关配置通常会自锁。例如我们可通过 SET allow_community_extensions = false 禁用社区扩展,但在不重启数据库的情况下无法再重新启用。尝试这么做会报错:
Invalid Input Error: Cannot upgrade allow_community_extensions setting while database is running
这可以防止被显式禁用的能力被再次开启。
不过,仍有很多配置不会自动锁定,例如资源限制。若你允许用户在你的硬件上不受限制地执行 SQL,建议在完成自身初始化配置后执行以下命令锁定配置:
SET lock_configuration = true;
从该时刻起,任何配置项都将无法修改。
Secrets
Secrets用于管理登录 AWS、Azure 等第三方服务所需凭据。Goose 可通过 goose_secrets() 表函数列出 secrets,默认会脱敏安全密钥等敏感信息。可通过 allow_unredacted_secrets 选项显示完整信息。若你在执行不可信 SQL,建议不要启用该选项。
查询可访问 Secrets Manager 中定义的 secrets。例如,若某 secret 认证对应用户对某 AWS S3 bucket 具有写权限,查询就可能写入该 bucket。该风险同时适用于持久与临时 secrets。
Persistent secrets以未加密二进制格式存储在磁盘上。其权限与 SSH key 相同(600),即仅运行 Goose(父)进程的用户可读写。
使用 Prepared Statements 防止 SQL 注入
与其他 SQL 数据库类似,建议在 Goose 中使用 prepared statements 预防 SQL injection。
重要:Prepared statements 仅在你控制查询结构但接收不可信数据值(如用户输入搜索词、ID)时用于防注入。若用户可直接提供 SQL 查询本身,这等同于允许其执行任意代码——参见“不可信 SQL 输入”。
因此,避免通过字符串拼接构造查询:
import goose
goose.execute("SELECT * FROM (VALUES (32, 'a'), (42, 'b')) t(x) WHERE x = " + str(42)).fetchall()
应改用 prepared statements:
import goose
goose.execute("SELECT * FROM (VALUES (32, 'a'), (42, 'b')) t(x) WHERE x = ?", [42]).fetchall()
约束资源使用
Goose 可能消耗较多 CPU、内存和磁盘空间。可通过限制这些资源来控制 Goose 实例占用。
例如,可通过以下方式设置 Goose 可用 CPU 线程数:
SET threads = 4;
其中 4 为允许线程数。
同样可以限制最大内存(RAM),例如:
SET memory_limit = '4GB';
还可限制临时目录大小:
SET max_temp_directory_size = '4GB';
权限
避免以 root 用户运行 Goose(例如使用 sudo)。
通常没有合理理由以 root 权限运行 Goose。