跳到主要内容

安全模型

Apache Fesod (Incubating) 是嵌入 Java 应用运行的电子表格处理库,其 Excel 处理能力基于 Apache POI 实现。本安全模型说明读写 Excel、CSV 及相关转换功能时的信任假设和责任边界。

成功生成的 XLSX 文件受到密码保护,不代表处理期间的所有数据也已加密。 明文可能存在于临时文件、缓存、输出位置和 JVM 内存中,应用与部署方需要分别保护这些位置。

适用范围与信任边界​

Apache Fesod (Incubating) 以所在 JVM 进程的权限执行文件访问、内存分配和已启用的网络操作。它不提供应用身份认证、业务授权或租户隔离机制。应用应使用受维护的 Apache Fesod (Incubating)、JDK 和依赖版本,并确认所部署版本的具体能力与配置。

对象或操作安全预期应用与部署方责任
应用代码、转换器、监听器和处理器自定义扩展作为受信任代码在同一 JVM 中执行不执行来自不可信用户的扩展代码;扩展可访问进程拥有的资源
输入文档、模板与单元格数据输入可能包含恶意或异常内容;解析和流式 API 不构成沙箱验证业务输入,限制资源消耗,按风险隔离处理进程
本地路径和文件流Apache Fesod (Incubating) 按调用方指定的路径或流读写校验路径授权,保护输入、输出及模板目录,隔离不同租户
临时文件与读取缓存中间数据可能包含未加密的工作簿或单元格内容防止不可信主体读取、修改或替换临时存储及其内容
JVM 内存、转储和日志可能包含敏感内容或密码分别控制调试、转储、日志、备份和运行身份的访问权限
URL 图片等网络功能默认禁止远程获取,需显式配置精确主机白名单才能启用;请求由 JVM 进程发起保持默认拒绝策略或限定目标,设置网络出口控制,不直接信任用户提供的 URL
密码保护的 XLSX 输出成功完成写入后,输出使用 Apache POI 的工作簿加密实现保护密码、处理中的明文和失败产物,确认写入成功后再交付

Apache Fesod (Incubating) 不保证对已能访问应用文件、临时存储或进程内存的主体隐藏相应数据。这些访问权限需要分别评估:能读取临时文件,并不意味着能读取 JVM 堆内存;反之亦然。

与 Apache POI 的关系​

使用 Apache Fesod (Incubating) 中基于 POI 的功能时,必须同时考虑 Apache POI 的安全指导、支持的行为和实现限制。Apache Fesod (Incubating) 提供上层 API,不会消除 POI 对临时存储保护、进程内存保护和资源隔离的要求,也不会消除底层文档格式与加密支持的限制。请结合应用所使用的 POI 版本,同时阅读 Apache POI 安全指导和本安全模型。

Apache Fesod (Incubating) 的目标是遵循 POI 的安全模型、API 约定和保护性检查,不通过封装绕过其安全措施,也不承诺超出底层实现能力的安全属性。应用不应仅为接受被安全检查拒绝的文档而关闭或削弱 POI 的保护措施。确有必要调整配置时,应遵循 POI 的文档约定,评估安全影响,包括对同一 JVM 内其他代码的影响。

这一依赖关系不免除 Apache Fesod (Incubating) 对自身代码和集成行为的责任。Apache Fesod (Incubating) 引入的异常行为,或通过其 API 绕过安全控制的情况,仍应通过私密渠道报告并评估。POI 支持某项能力,也不代表所有 Apache Fesod (Incubating) API 都已暴露或启用该能力。

临时文件与缓存​

Apache Fesod (Incubating) 及其依赖可能在读取、流式写入、模板处理和加解密过程中使用临时文件或磁盘缓存。即使最终工作簿受到密码保护,中间数据也可能以明文形式存在。

部署方必须为 JVM 配置受保护的临时目录,并保护应用或依赖另行配置的缓存、暂存和输出位置。不可信主体不得读取、修改或替换这些目录及其内容。随机文件名和共享目录的 sticky bit 均不能替代访问控制。

在 POSIX 系统中,可在应用启动前,以服务运行身份创建独立的临时目录:

umask 077
FESOD_TMPDIR="$(mktemp -d "${TMPDIR:-/tmp}/fesod.XXXXXXXX")" || exit 1
chmod 700 "$FESOD_TMPDIR" || exit 1
java -Djava.io.tmpdir="$FESOD_TMPDIR" -jar app.jar

父目录必须防止不可信主体替换该私有目录。Windows 部署应使用等效 ACL 限制访问。此示例保护默认 JVM 临时位置,其他显式配置的目录仍需单独保护。目录权限不能隔离共享同一操作系统身份的不可信租户。

在 JVM 启动时设置 java.io.tmpdir。在库初始化后修改该属性,不能确保所有组件随之切换目录。容器部署应采用受保护的工作负载专用临时卷,避免不可信工作负载共享可访问的暂存空间。

关闭读写器并完成其资源释放流程。在正常释放资源时,库及其依赖会尝试清理当前操作管理的临时文件和缓存,在适用的路径中也会删除该操作专用的临时子目录,但不保证清理一定成功。

库不会全面清扫共享临时目录,也不会统一清理先前运行或其他进程留下的残留文件。异常、强制终止、主机故障或删除失败都可能留下中间文件。运行环境必须保护临时存储,并对不再被活跃任务使用的残留文件实施受控清理。普通删除不等于安全擦除,也不会自动清除快照或备份。

密码保护​

对 XLSX 设置非空密码并成功完成写入后,最终工作簿使用 Apache POI 的加密实现。这一能力保护最终文件的内容,不提供从输入、处理、暂存到交付的全生命周期加密,也不提供用户身份认证、业务授权或密码强度保证。

加密模式由库选定,调用方无法指定。当前版本使用 Apache POI 的 standard 加密模式,即 Office Open XML 标准定义的 AES-128 与基于 SHA-1 的密钥派生,而非允许 AES-256 的较新 agile 模式。该模式决定了密钥长度和密钥派生方式,也决定了成品文件抵御离线密码猜测的能力。请核实所部署版本实际使用的模式,不要默认其强度更高;如果威胁模型依赖更强加密,应重新评估。这一能力面向静态存储与传输过程中的访问控制,不能替代对"谁可以获取或留存该文件"的控制,也不适合作为高价值机密的长期存储手段。

加密流程可能先生成明文工作簿,再生成加密结果。直接写入文件路径时,该位置在处理期间也可能包含明文。应用必须保护输出位置,并在整个写入流程成功完成之前禁止下载或公开结果。

使用 ExcelWriter 分批写入时,单次 write() 返回不代表输出或加密已完成。所有写入操作以及最终的 finish() 或 close() 都必须成功完成后才能交付;使用 try-with-resources 时,应在整个语句正常退出后再交付,而不是在其代码块内交付。

写入或加密失败后,应将结果视为未完成,停止交付并按敏感数据处理。不要假设异常必然留下加密文件、空文件或已清理的文件。对需要控制交付时机的场景,可先在受保护的暂存位置生成结果,成功后再发布。

内存模式不应被视为所有 Apache Fesod (Incubating) 与依赖执行路径均不落盘的承诺。CSV 没有工作簿密码加密能力,旧版 XLS 的保护不能假定具有与 XLSX 加密相同的保密性。

密码应由受控配置或密钥管理机制提供,避免出现在源码、日志和异常输出中。密码保护不能替代文件系统权限、传输保护或敏感数据留存策略。

不可信文档与资源隔离​

文档中的压缩数据、共享字符串、图片、样式和复杂结构可能导致较高的 CPU、内存或磁盘消耗。输入文件大小、扩展名及使用流式 API,均不足以保证处理成本有界。现有检查也不构成对所有恶意文档的完整防护。

OOXML 压缩包通过 Apache POI 读取,由 POI 对压缩条目施加自身的膨胀比限制。该限制能拒绝部分高压缩比输入,但它只是对膨胀倍数的启发式约束,不是可靠的隔离手段,不能替代进程级限制。

替换默认 XML 解析器工厂会改变读取时施加的解析器加固配置。库会对自身创建的解析器设置 DOCTYPE 与外部实体限制,但替换为不支持这些设置的工厂时,这些限制不会被强制执行。如果自行提供工厂,请确认等效防护已经生效。

处理外部文件时,应用应设置输入与输出大小、并发数、临时存储容量和业务处理量限制。对超时与内存耗尽需要可靠隔离的服务,建议在独立进程或容器中处理,并由外部监督程序限制运行时间、资源和网络访问。不要依赖线程中断作为终止所有解析工作的保证。

处理失败后,不应将部分导入结果或未完成导出视为业务成功。数据库事务、数据校验和任务重试策略由应用负责。

路径、网络与下游电子表格行为​

不要把用户输入直接作为具有任意访问能力的本地路径。应用应限定允许的读写根目录,校验实际目标的授权,并考虑符号链接和并发替换带来的影响。Apache Fesod (Incubating) 不理解调用方提供的路径在业务上属于哪个用户或租户。

对 URL 图片等网络功能,默认禁止远程获取,必须显式配置精确主机白名单才能启用。请求从服务端发出;允许访问某个域名也不等于允许访问其可能重定向或解析到的任意网络位置。自定义转换器执行的网络操作同样需要受控。

URL 获取策略是进程级配置,不随工作簿或读取器隔离。JVM 内任何代码都可以修改它,修改后会作用于该进程中所有使用 Apache Fesod (Incubating) 的组件,包括原本认为已禁用获取的组件。应在应用启动阶段一次性设置,避免各业务模块在运行期相互覆盖;多个库共享同一 JVM 时,应确认实际生效的策略。

Apache Fesod (Incubating) 不提供通用的公式、超链接、外部引用或 CSV 数据净化策略。导出内容随后被电子表格软件打开时,可能触发该软件的解释或交互行为。应用应区分普通文本与有意写入的公式,按数据来源和目标客户端制定输出策略;CSV 引号转义本身不消除公式注入风险。

漏洞报告与安全加固​

如果行为可能突破上述边界,或导致意外的数据泄露、文件访问、网络请求或代码执行,请先私下发送邮件至 security@apache.org,注明 Apache Fesod (Incubating),并提供版本、配置、攻击者已有权限、影响和最小复现。不要在公开 Issue、PR 或邮件列表中首先披露潜在漏洞的细节。

即使无法确定报告是否属于漏洞,也可以通过私密渠道提出。项目团队会结合实际行为、受影响版本和适用的安全期望来评估报告。依赖扫描结果应结合实际使用路径分析;涉及安全控制被绕过的报告,不能仅以部署方也负有责任为由排除。

以下情形通常不属于 Apache Fesod (Incubating) 自身的漏洞,因为边界在应用侧;但如果库本可以合理避免该结果,仍然值得报告:

  • 把不可信字符串直接作为本地路径传给库,根因是应用侧的路径穿越
  • 自行替换 XML 解析器工厂,或放宽 URL 获取策略,再依赖库恢复调用方已关闭的防护
  • 明文残留在应用配置的、未受保护的临时目录或输出目录中
  • 应用选择了弱密码,导致成品加密文件可被猜解

在受保护环境之外运行所带来的风险,通常需要通过部署配置解决。项目也欢迎降低误配置影响的加固建议,例如更严格的临时文件权限和更可靠的清理。是否构成漏洞、是否分配 CVE,以及是否采用某项加固,属于不同的评估事项。

支持的版本与披露流程​

安全修复只在最新发布线上提供,旧发布线不做回溯修复;报告前请先升级到受维护的版本,以免报告已被修复的问题。项目遵循 ASF 漏洞处理流程:报告在私密渠道讨论,修复准备完成后与报告者协调披露时间;当项目与 ASF 安全团队判定确有必要时,会申请 CVE。

相关资料​