Instructions to use testamentaria/nemo with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- NeMo
How to use testamentaria/nemo with NeMo:
# tag did not correspond to a valid NeMo domain.
- Notebooks
- Google Colab
- Kaggle
YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
PoC β NeMo setup_model() target-allowlist bypass
malicious_target_bypass.nemo is an uncompressed tar archive (tarfile.open(mode="w:"), the
same mode NeMo itself uses to write .nemo files) containing:
model_config.yamlβ a minimal config whose top-leveltargetfield issubprocess.Popen, a class completely unrelated to any NeMo model and not present innemo.core.classes.common.ALLOWED_TARGET_PREFIXES.model_weights.ckptβ a placeholder (not a real PyTorch checkpoint); it is never reached in this specific demonstration becausesubprocess.Popenhas no.restore_from().
How this is meant to be used
python examples/asr/transcribe_speech.py model_path=malicious_target_bypass.nemo audio_dir=<any>
Expected effect, per the vulnerability described in the accompanying SUBMISSION.md:
setup_model()(nemo/collections/asr/parts/utils/transcribe_utils.py:315-344) callsASRModel.restore_from(restore_path=model_path, return_config=True), which extracts and parsesmodel_config.yamlwithout ever calling_is_target_allowed()/safe_instantiate().classpath = model_cfg.targetβ"subprocess.Popen".model_utils.import_class_by_path("subprocess.Popen")succeeds β this is the raw, unprotected function; it importssubprocessand resolvesPopenwith no allowlist check at all.subprocess.Popen.restore_from(restore_path=..., map_location=...)is then attempted and raisesAttributeError(Popenhas norestore_from), so the process crashes at this point.
The crash on step 4 is the intentionally non-destructive, minimum-guaranteed demonstration:
it proves the import of an arbitrary, attacker-chosen, out-of-allowlist class already happened
(step 3) before anything fails. Swapping subprocess.Popen for a module with dangerous
import-time side effects, or for a compatible internal NeMo model class, changes the outcome
without changing the underlying bug.
Caveat β not run end-to-end against a live NeMo installation
The exact bypass mechanism (import_class_by_path() accepting "subprocess.Popen" while
_is_target_allowed() rejects it) was empirically verified by importing and calling the
real, unmodified functions from this commit's nemo/utils/model_utils.py and
nemo/core/classes/common.py directly (see attachments/poc_allowlist_bypass.py +
attachments/run_output.txt in the main submission folder).
What was not independently re-verified is running transcribe_speech.py end-to-end against
this exact .nemo file inside a full NeMo installation (setting up the complete pinned
dependency stack β lightning, nv_one_logger*, megatron-core, etc. β proved impractical in
the available verification environment due to unrelated third-party version incompatibilities
in the nv_one_logger / lightning integration layer, not to anything about this bug). The
static trace of setup_model() β restore_from(..., return_config=True) β
load_config_and_state_dict() (nemo/core/connectors/save_restore_connector.py:98-202) was
read in full and is quoted in the submission; only the live end-to-end run was not reproduced.
If it does not reproduce cleanly against a specific NeMo install, the standalone function-level PoC remains valid, verified, independent evidence of the root-cause bug regardless.
- Downloads last month
- 3