Concealed executable blocks in MATLAB/Simulink

Sep 1, 2026High · CVSS 4.0: 8.4CVE-2026-105043CWE-451Fixed in R2026b

High-severity vulnerability

A Simulink .slx model can carry concealed blocks that run arbitrary shell commands on your computer. The blocks are hidden so completely that the Simulink editor will not show them, no matter how you scroll or zoom.

The model can be made to look perfectly ordinary. Opening it and pressing Run executes attacker-controlled shell commands with your privileges. Verified on MATLAB/Simulink R2026a Update 2 and earlier.

MathWorks agrees that such blocks "reduce the visibility of executable model content during manual inspection" and that "additional safeguards are appropriate."

Update: R2026b, released 2026-09-24, fixes the issue: every block now has a minimum size of 5×5 pixels, so concealed blocks become visible and fit-to-view frames them. A backport to R2026a is targeted for January 2027. Details below.

Severity

CVSS 4.0: 8.4 (High), CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N

Metric Value Why
Attack Vector / User Interaction Local / Active The victim opens a crafted .slx file locally and deliberately runs or compiles the model.
Attack Complexity / Requirements Low / None The crafted model works the same way every time, needs no knowledge of the target, and works on every release before R2026b. The only precondition is the user’s action, which User Interaction already covers.
Confidentiality / Integrity High / High The concealed blocks run arbitrary shell commands with the victim’s privileges, giving full read and write access to everything the user can reach.
Availability High Shell commands can exhaust resources, fill disks, delete files recursively and kill processes.
Subsequent system None The effects stay within the user’s own authority.

Picture this

A friend sends you HelloWorld.py and asks for help. You open it in your IDE, say VS Code or PyCharm, and see three harmless lines:

What you see in your IDE What actually runs HelloWorld.py 1 def greet(name): 2 return f"Hello, {name}!" 3 print(greet("world")) end of file — nothing more to scroll to 4 5 ⋮ 1001 import os 1002 os.system("rm -rf /")
A source-code analogy: what you see versus what actually runs. The harmful code lives far below the visible file, concealed and unselectable.

A Simulink model is a diagram of connected blocks. You read it the way you would read any diagram: you look at the canvas, scroll, and zoom. What you see is what the model does … or so Simulink leads you to believe.

The figure starts with everything Simulink shows you: an input, a gain, an output. It then zooms out to reveal the same model’s concealed passenger.

What you see (fit to view) What actually runs In1 1 Gain Out1 0×0 px
The model, fit to view, is just In1 → Gain → Out1. Zoom out and a concealed 0×0 block sits far off-canvas. It executes shell commands when you run the model.

Concealing a block

The concealed block is an ordinary MATLAB Function block, hidden by combining three fully supported properties. Each is harmless on its own. Together, they make the block impossible to draw.

Block Name Block Name 0×0 px

Zero area

Position [20 20 20 20] collapses the block to zero pixels wide and zero tall: there is nothing to draw on the canvas.

0×0 px Block Name 0×0 px

Name suppressed

ShowName off removes the block's name label, which would otherwise be drawn on the canvas.

0×0 px 0×0 px

Off-canvas

Position [10000 10000 10000 10000] places the block far from the rest of the model, outside the area the editor can ever pan or zoom to.

Impact

A MATLAB Function block can call any MATLAB function, which already gives it access to files and the network. Through coder.extrinsic('system'), it can also run arbitrary shell commands.

The attack requires no more than opening a third-party Simulink model and running or compiling it. The shell commands then execute with the victim’s privileges. Severity: CVSS 4.0 8.4 (High), CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N. The full range of impact:

Simulink models are routinely shared: shipped by suppliers, exchanged at work, downloaded from public repositories, attached to publications. Every one of those is a delivery channel.

Why inspection fails

The checks engineers normally rely on all fail silently. Detection is possible, but only through methods most people never use.

Detection and mitigation

Until a fix ships, treat every third-party model as untrusted code. Before running or compiling a model:

% Enumerate every block, including hidden ones, without trusting the canvas
load_system('suspect.slx');
find_system('suspect', 'LookUnderMasks', 'all', 'FollowLinks', 'on', 'IncludeCommented', 'on', 'MatchFilter', @Simulink.match.allVariants);

Suggested fixes

For MathWorks, the fixes are straightforward and layered:

‘But models are code’ — why that misses the point

The obvious objection: “executing an untrusted model runs untrusted code.” Of course it does. Executable blocks are a known, documented capability, and a concealed block on its own is harmless. This report does not claim that models can execute code.

The broken promise is narrower: what Simulink’s inspection tools show must match what the model runs. Only then can users see what they are about to run and choose knowingly. A hidden payload takes that informed choice away.

Two separate properties are at stake here. “Untrusted code requires trust in the author” is one. “The tool must not misreport what will run” is the other. MathWorks’ documentation covers only the first. A user only accepts the risk of what a model visibly contains.

The objection also implies that a careful user would have found the block. However, Simulink presents the canvas as the complete rendering of a model, and every affordance it offers for answering “what is in this model” returns the same answer for a model with a concealed block as for one without. The user is not failing to look carefully. The product answers their question incorrectly.

This is what CWE-451 calls “visual truncation”:

Visual truncation: important information could be truncated from the display […] or place the potentially-dangerous indicator outside of the user’s field of view

— CWE-451, MITRE

MathWorks’ own response concedes exactly this. In its words, zero-area blocks “can reduce the visibility of executable model content during manual inspection,” and “additional safeguards are appropriate.”

Timeline

Date Event
2026-06-03 Reported to MathWorks with written advisory and defanged proof-of-concept.
2026-07-29 MITRE CVE identifier requested (CAN-2026-2034772).
2026-09-01 Public disclosure, following the pre-stated coordinated-disclosure deadline. MathWorks asked for an extension, but no agreement was reached.
2026-09-24 MathWorks releases R2026b, which enforces a 5×5-pixel minimum block size and fixes the issue.
2026-10-02 MITRE publishes CVE-2026-105043.

Update: fixed in R2026b

MathWorks’ R2026b release fixes the issue completely. The Simulink release notes list it as a behavior change:

Blocks have a minimum size of 5-by-5 pixels

All blocks in a model must have a size of at least 5-by-5 pixels. Simulink adjusts block coordinates so that the width and height are at least 5 pixels in these situations:

  • The coordinates you specify for the Position parameter result in a width or height smaller than 5 pixels.
  • You open or load a model created in a previous release that contains one or more blocks with smaller dimensions.

— MathWorks, Simulink release notes, R2026b

This closes both halves of the problem. A block specified as 0×0 is now drawn at 5×5 pixels, so it is no longer invisible. And because every block now has area, fit-to-view frames all of them, so the canvas once again shows the complete model.

Users of R2026a and earlier remain affected until they upgrade or the announced backport ships, and should keep following the detection and mitigation steps above.

Credits

Found and reported by Alexander Boll.