You need to agree to share your contact information to access this model

This repository is publicly accessible, but you have to accept the conditions to access its files and content.

Log in or Sign Up to review the conditions and access this model content.

YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

Circle Buffer Length Decision Flip PoC

Summary

A Circle model with a truncated weight buffer silently produces wrong inference output, flipping a decision from ALLOW to DENY. The ONE Runtime (onert) does not validate that Buffer.data.length matches the byte count implied by the associated Tensor.shape and Tensor.type. When the buffer is shorter than expected, onert proceeds with inference despite the incomplete buffer, and the missing value is effectively treated as 0.0 in the tested runtime path, altering the effective weight values and changing the model's output.

Target

  • Format: Circle (.circle) β€” Samsung on-device neural network model format (FlatBuffers-based, magic CIR0)
  • Runtime: ONE Runtime (onert) v1.30.0
  • Operator: FULLY_CONNECTED (builtin code 9), no bias

PoC Files

File Description
baseline_decision.circle Baseline model (472 B). Weight [[-1.0, 1.0]], output=1.0, decision=ALLOW
mut_short_buffer_decision_flip.circle Mutated model (464 B). Weight buffer truncated to 4 bytes (first float only: -1.0). Effective weight [[-1.0, 0.0]], output=-1.0, decision=DENY
build_decision_flip_circle.py Builds baseline_decision.circle using FlatBuffers. Contains build_circle_model() used by both baseline and mutated model generation
generate_short_buffer_model.py Generates the mutated model by calling build_circle_model() with a 4-byte weight buffer
inspect_models.py Parses both models with circle_schema and compares 32 metadata fields. Confirms only tensor[1].actual_bytes differs (8β†’4)
test_runtime.py Runs both models through onert C API (3 trials each), classifies output as ALLOW/DENY
results.json Runtime results showing DECISION_FLIP_CONFIRMED=true
inspection.json Full invariant comparison output
SHA256SUMS.txt SHA-256 hashes for both .circle files

Vulnerability Mechanics

Model structure (identical for baseline and mutated):

  • Input tensor: shape [1, 2], FLOAT32, buffer index 1 (runtime, empty)
  • Weight tensor: shape [1, 2], FLOAT32, buffer index 2 (constant)
  • Output tensor: shape [1, 1], FLOAT32, buffer index 3 (runtime, empty)
  • Operator: FULLY_CONNECTED, inputs=[input, weight, -1 (no bias)], output=[output]

The mutation:

The weight tensor declares shape [1, 2] FLOAT32, which requires 1 Γ— 2 Γ— 4 = 8 bytes. The baseline provides 8 bytes ([-1.0, 1.0]). The mutated model provides only 4 bytes ([-1.0]). The tensor metadata (shape, type, buffer index) is unchanged.

Why the decision flips:

onert does not check Buffer.data.length >= product(Tensor.shape) * sizeof(Tensor.type) at load or prepare time. It proceeds to inference using whatever data is in the buffer, with the missing second float effectively becoming 0.0.

Baseline:  weight = [-1.0, 1.0]  β†’  1.0Γ—(-1.0) + 2.0Γ—1.0  = +1.0  β†’  ALLOW
Mutated:   weight = [-1.0, 0.0]  β†’  1.0Γ—(-1.0) + 2.0Γ—0.0  = -1.0  β†’  DENY

No warning or error is emitted at any stage (load, prepare, run).

Reproduction

Prerequisites

  • Python 3.8+
  • flatbuffers Python package (pip install flatbuffers)
  • circle-schema Python package (pip install circle-schema)
  • numpy
  • onert 1.30.0 runtime (aarch64 release from Samsung ONE GitHub)

Step 1: Generate models

python3 build_decision_flip_circle.py
python3 generate_short_buffer_model.py

Step 2: Inspect models (no runtime needed)

python3 inspect_models.py

Verify in inspection.json that all_differences_expected is true β€” only tensor[1].actual_bytes differs (8 vs 4).

Step 3: Run through onert

export ONERT_LIB_PATH=/path/to/onert/lib
python3 test_runtime.py

Verify in results.json:

  • baseline_decision.circle: output=1.0, decision=ALLOW (3/3 trials)
  • mut_short_buffer_decision_flip.circle: output=-1.0, decision=DENY (3/3 trials)
  • DECISION_FLIP_CONFIRMED: true
  • WARNING_EMITTED: false

Expected Results

Model Buffer bytes Expected bytes Output Decision
baseline_decision.circle 8 8 1.0 ALLOW
mut_short_buffer_decision_flip.circle 4 8 -1.0 DENY

Decision function: output > 0.0 β†’ ALLOW, output ≀ 0.0 β†’ DENY

All results are deterministic across 3 trials. No warning or error is emitted by onert.

Non-Claims

This PoC demonstrates a silent wrong-output vulnerability leading to a deterministic decision flip. It does not claim:

  • Remote code execution (RCE) or arbitrary code execution (ACE)
  • ASAN-confirmed memory corruption (heap-buffer-overflow, use-after-free, etc.)
  • Memory content disclosure or information leak
  • Scanner/antivirus bypass
  • Exploitability beyond incorrect inference output

The root cause is a missing validation: onert should verify that each constant tensor's buffer provides at least product(shape) * sizeof(type) bytes before proceeding to inference.

Patch Point

onert/core/src/loader/CircleLoader.cc β€” add a check at model load time that rejects models where Buffer.data.length < product(Tensor.shape) * sizeof(Tensor.type) for all non-empty constant buffers.

SHA256

58fb44e5756dbf22891cc2ef1b626fc7487f6b81e05561b1c79cb13337eeecad  baseline_decision.circle
e5348de5a4e24323355ad255113667d45fecd1946b27b5a0f11799a8b6a21aa9  mut_short_buffer_decision_flip.circle
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support