Path traversal / arbitrary file read via the `file_name` metadata field in `*folder` dataset builders (no `trust_remote_code`)

### Describe the bug

reported via email on 9 June 2026 - no acknowledgement or response:

Package: datasets (PyPI). Affected file: src/datasets/packaged_modules/folder_based_builder/folder_based_builder.py
Affected Versions: confirmed on 5.0.0 (PyPI) and HEAD 63e103e.
CVSS: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N  (~7.1 High when the exfil/re-embed chain applies; Medium for local read only)
CWE: CWE-22 Path Traversal

## Summary

The built-in `imagefolder` / `audiofolder` / `videofolder` / `pdffolder` (`*folder`) builders read a `file_name` value verbatim from a dataset's `metadata.jsonl`/`.csv`/`.parquet` and join it to the dataset directory without neutralizing `..` or absolute paths. A malicious dataset can therefore make `load_dataset(...)` open and read files **outside** the dataset directory. No `trust_remote_code` is required (these are packaged builders).

## Details

`src/datasets/packaged_modules/folder_based_builder/folder_based_builder.py` (~L404-405):

```python
file_relpath = os.path.normpath(item).replace("\\", "/")   # item = attacker-controlled file_name
item = os.path.join(downloaded_metadata_dir, file_relpath)  # join escapes the dataset dir
```

`os.path.normpath` canonicalizes separators but does **not** strip a leading `../`, so `../../../../etc/passwd` survives, and an absolute value escapes entirely. No `commonpath`/`relpath`/`realpath` containment check exists. The resolved path is stored in the `Image`/`Audio`/`Pdf` feature and then read:
- `features/image.py:175` `PIL.Image.open(path)` (lazy read on row access), and
- `features/image.py:311` `xopen(path,"rb").read()` in `embed_storage` — the unconditional raw-byte read used by `save_to_disk` / `push_to_hub`.



### Steps to reproduce the bug

## PoC 
`metadata.jsonl` in an `imagefolder` dataset:
```json
{"file_name": "../victim/secret.png", "text": "x"}
```
```python
from datasets import load_dataset
d = load_dataset("imagefolder", data_dir=malicious_dir, split="train")
d[0]["image"]   # the image OUTSIDE the dataset dir
```
Observed: `OUT-OF-DATASET READ: True` (loaded the out-of-directory image). With `file_name: "../../../../../../etc/passwd"`, the path resolves to `/etc/passwd`; the `embed_storage` path (invoked by `save_to_disk`/`push_to_hub`) pulled the bytes of `/etc/passwd` into the saved output (`EXFIL CONFIRMED`).

## Impact

Loading a malicious dataset reads arbitrary local files; when the victim re-saves/re-publishes (`save_to_disk`/`push_to_hub`) the dataset, arbitrary local file contents are silently embedded into the output and exfiltrated. Triggered by the ordinary `load_dataset("imagefolder", data_dir=...)` and identically for a remote Hub dataset `load_dataset("user/dataset")`.

## Net-new

No matching CVE/GHSA. Distinct from the tarfile (CVE-2007-4559) mitigations in `utils/extract.py`, which were tested separately and correctly block `..`/symlink escapes — the flaw here is the unsanitized `file_name` metadata join, not archive extraction.

## Remediation

Reject `file_name` values that are absolute or contain `..` (require the resolved path to remain under the dataset/metadata directory via `os.path.realpath` + `os.path.commonpath`, or restrict to `os.path.basename`-relative paths within the tree).


### Expected behavior

-

### Environment info

-


#self-assign