Concealed executable blocks in MATLAB/Simulink
Critical 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 plans to ship a fix in the upcoming R2026b release at the end of September, and will attempt to backport the fix to earlier versions.
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:
Now in Simulink
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.
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.
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.
Name suppressed
ShowName off removes the block's name label, which would otherwise be drawn on the canvas.
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. The full range of impact:
- Code execution — downloading and running a further payload.
- Confidentiality — directory listing and data exfiltration.
- Integrity — overwriting or deleting files.
- Availability — resource exhaustion and infinite loops.
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.
- ✗Fit-to-view — should frame every block but frames only what has area; a 0×0 block gives it nothing to include, so you believe the canvas shows every block.
- ✗Zoom and pan — the concealed block is too far off-canvas to reach, and even at the canvas limits nothing appears.
- ✗Rubber-band drag — the block lies beyond any region you can drag a selection over, and even a successful selection would give no visible feedback.
- ✗Select-All (Ctrl+A) — selects the hidden block, but produces no visible feedback anywhere.
- ✓find_system() — enumerates every block programmatically, hidden or not.
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);
- Flag dimensionless blocks whose four
Positioncoordinates are equal, or that sit far from other blocks. - Scrutinize blocks that call
coder.extrinsic('system'). Such a function can reach the shell and should not be trusted in a third-party model. - Prefer a sandbox. Open models on a throwaway machine or container with no network and no sensitive files.
Suggested fixes
For MathWorks, the fixes are straightforward and layered:
- Enforce a minimum block geometry (at least 1×1 pixel) so zero-area blocks cannot slip past rendering and selection.
- Add edit-time / Model Advisor checks for zero- or near-zero-area blocks, blocks placed far outside the canvas bounds, blocks fully covered by others, and MATLAB Function blocks that declare extrinsic shell functionality.
- Provide a hidden-block inventory so that “show me everything in this model” through the GUI is actually complete.
‘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.
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 choice away.
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
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. |
MathWorks has acknowledged the report and plans to fix it in the next release, with a backport to follow. A MITRE CVE is pending.
Credits
Found and reported by Alexander Boll.