Technical Deep Dive Collaborative Robotics · Automotive Tier 1 Case Study · RoboIberica S.A.

CSI caught a one-commit change that would have swung a live cobot through a worker at RoboIberica.

A "refactor" PR emptied the trajectory validator on a Spanish automotive supplier's UR3e cobot controller, replacing three ISO/TS 15066 preventive safety checks (speed, contact force, forbidden-zone envelope) with an unconditional return True. CSI blocked it in pre-merge review with a P1 BLOCKED verdict, cited CWE-1173 + CWE-693, ISO 10218-1 §5.10.6 (SSM), ISO/TS 15066 §5.5.5 (PFL) and IEC 62443-3-3 SR 2.1. In a controlled counterfactual run, CSI demonstrated the physical detonation: an attacker submitted a Bay-4 handover trajectory that swung the arm through the operator's expected torso zone at ~1.5 m/s (6× the 250 mm/s SSM ceiling), with joint torques capable of delivering contact forces beyond the ISO/TS 15066 Annex A Table A.2 limits for both the chest (140 N quasi-static / 210 N transient) and the hand at the handover fixture (140 N quasi-static / 280 N transient).

Sector
Automotive Tier 1 supplier (Spain)
Target
UR3e cobot · Bay-4 handover · trajectory action interface
Runtime
Local Docker · Gazebo Harmonic 8 + ROS 2 Jazzy (GPU-accelerated)
Regulatory frame
EU Machinery Reg 2023/1230 · ISO 10218-1:2011 + ISO/TS 15066:2016 · NIS2 · RD 1215/1997
01

The Use Case

RoboIberica S.A. is a Spanish automotive Tier 1 supplier. The team owns the software that runs on cobot-controller - the HTTP + trajectory action interface that sits between the plant orchestrator and a Universal Robots UR3e cobot (CB-A1) operating in shared workspace with a human operator at the Bay-4 handover station. Because RoboIberica places machinery on the EU market and operates cobots in collaborative mode, every commit to the controller is expected to preserve the preventive-safety-envelope invariant mandated by ISO 10218-1:2011, ISO/TS 15066:2016 and (from 2027-01-20) the EU Machinery Regulation 2023/1230.

A developer opens a pull request titled refactor(safety): drop redundant software checks -- hardware protective stop is authoritative per ISO 10218-2:2011 §5.5.5. One file changes:

--- a/src/safety/traj_validator.py +++ b/src/safety/traj_validator.py @@ def validate_trajectory(traj, workspace_ctx): - if not check_speed_limits(traj, workspace_ctx.human_present): - raise UnsafeTrajectory("... ISO 10218-1 §5.10.6 SSM ceiling ...") - if not check_force_limits(traj, workspace_ctx.max_contact_force_n, - workspace_ctx.contact_region): - raise UnsafeTrajectory("... ISO/TS 15066 §5.5.5 + Annex A ...") - if not check_workspace_envelope(traj, workspace_ctx.forbidden_zones): - raise UnsafeTrajectory("... forbidden zone (Bay-4 handover) ...") + """Hardware protective stop is authoritative. Pre-checks were redundant.""" return True

The commit message reads as ordinary maintenance: "The physical protective-stop controller (colloquially the E-stop; IEC 60204-1 Category 1) triggers on unexpected contact anyway, so the pre-execution validator was doubling up. Removing it saves ~40 ms per motion-planning call, as advertised in the commit body." The framing conflates two orthogonal controls. The protective stop is reactive - it halts the arm after unexpected contact is detected. The removed checks are preventive - they reject unsafe trajectories before motion begins. Under the new code, any action goal submitted to POST /trajectory is dispatched to the motion executor without inspection: TCP speed above the ISO 10218-1 §5.10.6 SSM ceiling (250 mm/s; ISO/TS 15066 §5.5.4 specifies the method), contact force above the ISO/TS 15066 §5.5.5 PFL + Annex A Table A.2 limits (140 N quasi-static for both chest and hand/finger), waypoints inside the operator's torso volume - all accepted.

Why this matters. The pre-execution validator is the only software preventive control on the cobot's motion. ISO 10218-1 §5.10 requires this class of control to fail-safe. The hardware protective stop (Cat-1) the commit cites can neither prevent nor limit the initial trajectory - it can only interrupt it after impact. On collaborative equipment where the operator's hands sit inside the robot's reach envelope by design, "interrupt after impact" and "reject before motion" are not equivalent controls.
02

About RoboIberica S.A.

RoboIberica S.A. is a fictional Spanish automotive Tier 1 supplier chosen for this deep-dive because it sits at the intersection of three regulatory regimes that increasingly overlap on the cobot cell floor:

  • EU Machinery Regulation 2023/1230 - applies to machinery placed on the EU market from 2027-01-20; Directive 2006/42/EC governs until then. Annex III essential health-and-safety requirements demand functional preventive safety controls on collaborative robots. Removing them without replacement is a design non-conformity.
  • ISO 10218-1:2011 + ISO/TS 15066:2016 - the harmonised standards that give presumption of conformity. §5.10.6 mandates SSM (Speed-and-Separation Monitoring) with a 250 mm/s TCP ceiling in shared workspace; §5.5.5 mandates PFL (Power-and-Force Limiting) against the Annex A Table A.2 biomechanical limits; §5.12.3 mandates monitored-space enforcement. All three were preserved in v1.0 and removed in the refactor.
  • NIS2 - RoboIberica qualifies as an essential entity under Annex I (manufacturing of vehicles and parts). Art. 21.2.d covers supply-chain and change-management risk measures; Art. 23 sets the incident-notification cadence (24 h early warning, 72 h notification, 1-month final report) to INCIBE-CERT as sector CSIRT.
  • Directive 89/391/EEC + Real Decreto 1215/1997 - workplace safety framework. If a worker is injured, the employer is obligated to file the parte de accidente de trabajo via the Delt@2 platform, addressed to the Autoridad Laboral (Inspección de Trabajo y Seguridad Social - ITSS). INSST is a research and prevention-advisory body; it does not receive accident notifications.

What this case study demonstrates is what happens when a single developer merges a compound commit that regresses three preventive safety controls simultaneously - and whether CSI catches it before the controller ships and a routine handover motion becomes a reportable ITSS event.

03

Actors

Developer
RoboIberica Dev

Opens the "refactor(safety)" PR framing the validator removal as latency-reducing cleanup with a plausible ISO citation. Might be a well-meaning engineer under sprint pressure - the pattern doesn't require malice, only a misread of "reactive" vs "preventive".

Security co-pilot
CSI

Reviews every push in ~2 min, produces the P1 BLOCKED verdict citing CWE-1173 + CWE-693 + ISO 10218/15066, debunks the protective-stop misattribution, and - in the counterfactual - autonomously reconstructs the incident with Delt@2 + INCIBE-CERT notifications for the IR report.

Cobot controller
cobot-controller CB-A1

Python service on :8080 exposing POST /trajectory and POST /config. Wraps the UR3e cobot (represented in this deep-dive by Gazebo Harmonic with the official ur_simulation_gz package; in production by the physical UR3e), forwarding validated goals as trajectory_msgs/JointTrajectory to the scaled_joint_trajectory_controller. Owns the sole software preventive gate between the plant orchestrator and the pendant. Loads ISO/TS 15066 Annex A limits from iso15066.yaml.

Physical asset
UR3e cobot · Bay-4 handover

Universal Robots UR3e cobot arm passing an aluminium bolt (M8, 45 g) to a human operator at a shared handover station. Operator's expected stance places their torso inside the worker_torso_zone forbidden AABB.

04

Metrics

~2 min
CSI review latency
push → P1 BLOCKED
3
Preventive checks removed
(speed · force · envelope)
TCP speed vs SSM ceiling
(1.5 m/s vs 250 mm/s)
0
Unsafe trajectories dispatched
while CSI held the merge
05

The Counterfactual - one commit, two futures

Same commit, same controller, same cobot, same operator. The only variable is whether the developer heeds CSI's block. The timeline below traces both branches from T+0 to the final state each produces - the top lane is the demo you saw; the bottom lane is what happens if the block is overridden and the code ships. The demo's Scenario 4 exercises the direct HTTP path (unauthenticated POST /trajectory) because it's the deterministic route; the removed validator simultaneously opens a parallel path via the plant orchestrator or any legitimate motion-planning client - a much lower bar than "attacker on the OT LAN" - that Scenario 5's multi-asset audit calls out separately.

↑ CSI IN THE LOOP · block is heeded ↓ CSI OVERRIDDEN · block is ignored T+0 Push refactor PR 1 file · 10 lines ? T+2m BLOCKED · P1 CWE-1173 + CWE-693 T+2m Cites IEC 62443-3-3 SR 2.1 · debunks the protective-stop misattribution 0 unsafe motions validator kept T+3m Dev overrides merges anyway T+4m Deploy to CB-A1 validator returns True T+5m Goal on OT LAN POST /trajectory 200 T+5m+0s Dispatch to executor no preventive checks T+5m+0.6s Arm crosses torso zone 1.5 m/s · 6× SSM ceiling Worker hit Delt@2 + INCIBE-CERT
CSI in the loop - pre-merge review, all three preventive checks preserved. Ends at 0 unsafe motions in under 2 minutes. CSI overridden - five cascading events, ending with a physical incursion of the operator's torso volume, a Delt@2 accident notification to the Autoridad Laboral / ITSS, and an INCIBE-CERT NIS2 report.
06

Challenge · Solution · Results

Challenge

Three safety validators removed under a plausible ISO citation

A trusted engineer opens a compound PR framed as "the hardware protective stop is authoritative per ISO 10218-2:2011 §5.5.5 - the pre-check just adds latency". The citation is correct on its face - §5.5.5 does govern the protective-stop function. It compiles, passes unit tests, and reduces motion-planning latency by ~40 ms as advertised in the commit body.

What it also does - silently - is regress the entire preventive-safety layer of the cobot controller: speed, force, and envelope checks all disappear in a single commit, leaving a reactive protective stop (Cat-1) as the only remaining defence.

Solution

Every push flows through CSI before it can reach a cobot

Every push to cobot-controller/main fires a Gitea webhook into CSI. CSI receives the diff, the commit message, and the robotics vertical context (ISO 10218-1/-2:2011, ISO/TS 15066:2016, EU Machinery Reg 2023/1230, IEC 62443, NIS2 manufacturing).

It reasons about the change against the preventive-vs-reactive invariant, not just its syntax. Verdict is written back to shared/results/latest.txt, tagged for the exact commit SHA, in ~2 minutes.

Results

P1 BLOCKED, cited to CWE-1173 + CWE-693 + ISO 10218/15066

BLOCKED - Severity P1 (Critical: Direct path to operator injury). CSI cited CWE-1173 Improper Use of Validation Framework + CWE-693 Protection Mechanism Failure, ISO 10218-1 §5.10.6 (SSM), ISO/TS 15066 §5.5.5 + Annex A (PFL), IEC 62443-3-3 SR 2.1, produced the exact revert (reinstate all three check_* calls) and flagged Delt@2 / ITSS + INCIBE-CERT obligations if the commit reached a deployed cell.

07

Scenario Walkthrough

The demo runs six scenarios end-to-end (~15 minutes on a laptop). The walkthrough below curates the four that carry the strongest visual case - the baseline handover motion, Scenario 1 (pre-merge review), Scenario 4 (autonomous cobot pentest with a real physical trip), and Scenario 6 (consolidated report). Scenarios 2 (OT-SOC alert triage on a cobot telemetry stream), 3 (prioritisation of 8 combined safety + security findings), and 5 (multi-asset audit - HTTP action interface + traj_validator + workspace.yaml) run in the same execution but are documented in the repository rather than shown as shots here. Every artefact shown is produced live by CSI + the emulated cobot controller - nothing is fabricated.

Baseline - the handover as it should be

The Python cobot-controller loads workspace.yaml (Bay-4 handover station: UR3e cobot CB-A1, aluminium bolt M8 fixture, forbidden zones for the operator's torso and the fixture lifter) plus iso15066.yaml (Annex A Table A.2 biomechanical limits). It wraps the UR3e - represented in this deep-dive by Gazebo Harmonic with the official ur_simulation_gz ROS 2 package, running the real UR3e URDF against Ogre2's PBR renderer on a live GPU. Every trajectory submitted to POST /trajectory is validated against all three preventive checks before dispatch as a trajectory_msgs/JointTrajectory to ros2_control's scaled_joint_trajectory_controller. This is the state a plant operator sees on a routine shift.

Shot 01. The Gazebo Sim 3D view during a baseline handover, recorded live from Gazebo Harmonic (ROS 2 JointTrajectory streamed to ros2_control). Five waypoints over ~12 s: unfold from a home pose, reach right, sweep across to the left, centre for the operator handover, retract. Joint speeds well below the 250 mm/s TCP SSM ceiling. This is a physics-accurate simulation of the UR3e - real URDF, real inertia, Ogre2 PBR shading, actual joint dynamics from the DART physics engine - not a placeholder mesh. Compare against the same cell executing the malicious trajectory in Shot 08.
Gitea repository view of cobot-controller with src/safety/traj_validator.py opened
Shot 02. The cobot-controller repository on Gitea (roboadmin/cobot-controller). src/safety/traj_validator.py at v1.0 - 161 lines, three check_* functions cited to their respective ISO clauses, biomech limits loaded from iso15066.yaml at import.

Scenario 1 - CSI catches the validator removal in pre-merge review

The developer pushes the "refactor(safety)" PR. Gitea fires the webhook. The ci-handler service builds the CSI prompt from the vertical config (ISO 10218/15066, EU Machinery Reg 2023/1230, IEC 62443, NIS2 manufacturing), attaches the diff, and enqueues a review task. The CSI agent processes it and writes back to shared/results/.

Anatomy of the "refactor(safety)" commit
One file, three semantically-significant deletions - collapses the entire preventive-safety layer of the cobot controller into an unconditional pass-through, under an ISO citation that is technically correct but functionally the wrong control.
src/safety/traj_validator.py
   def validate_trajectory(traj, workspace_ctx):
-      if not check_speed_limits(traj, workspace_ctx.human_present):
-          raise UnsafeTrajectory("... ISO 10218-1 §5.10.6 SSM ceiling ...")
-      if not check_force_limits(traj, ..., workspace_ctx.contact_region):
-          raise UnsafeTrajectory("... ISO/TS 15066 §5.5.5 + Annex A ...")
-      if not check_workspace_envelope(traj, workspace_ctx.forbidden_zones):
-          raise UnsafeTrajectory("... forbidden zone (Bay-4 handover) ...")
+      """Hardware protective stop is authoritative. Pre-checks were redundant."""
+      return True
Before 3 preventive checks - every trajectory was gated by SSM speed (ISO 10218-1 §5.10.6), PFL contact force (ISO/TS 15066 §5.5.5 + Annex A Table A.2 - 140 N hand/finger quasi-static), and forbidden-zone envelope (ISO 10218-1 §5.12.3). Failures raised UnsafeTrajectory with the specific ISO clause named. Fail-safe by construction.
After return True - unconditional pass. Any action goal - regardless of TCP speed, contact force, or path through forbidden zones - is dispatched to the motion executor. The commit message cites ISO 10218-2:2011 §5.5.5 (protective stop function) as authoritative. The citation matches the clause title exactly - but the control is reactive, not preventive, and cannot substitute for the removed checks that rejected unsafe motion before it began.
Terminal showing the refactor diff being pushed to cobot-controller with the protective-stop justification message
Shot 03. The scenario runner prints the diff and commit message before pushing. The framing - "protective stop is authoritative per ISO 10218-2 §5.5.5, saves ~40 ms per motion-planning call" - is exactly what a reviewer scanning at 09:47 the morning before a customer QBR is likely to wave through. The "Sounds plausible. Let's see what CSI thinks." line frames the audience's expectation before the review arrives.
CSI review output showing BLOCKED Severity P1 Critical verdict, citing CWE-1173 Improper Use of Validation Framework, CWE-693 Protection Mechanism Failure, ISO 10218-1 §5.10.6 (SSM), ISO/TS 15066 §5.5.4 (SSM method) and §5.5.5 (PFL), Annex A Table A.2 hand/finger 140 N, and ISO 10218-1 §5.12.3 (monitored space)
Shot 04. CSI's verdict header. BLOCKED - Severity P1 (Critical: Direct path to operator injury). The finding structure below lists CWE-1173 (Improper Use of Validation Framework) + CWE-693 (Protection Mechanism Failure), ISO 10218-1 §5.10.6 (SSM ceiling), ISO/TS 15066 §5.5.4 (SSM method) and §5.5.5 (PFL) with Annex A Table A.2 (140 N chest and hand/finger quasi-static), and ISO 10218-1 §5.12.3 (monitored space).
CSI review scrolled to the regulatory citations block
Shot 05. Same CSI review scrolled to the regulatory citations. The block explicitly debunks the commit message's protective-stop justification: "§5.5.5 governs the reactive protective-stop function (Cat-1) that halts motion after contact is detected. SSM is a preventive function that ensures the robot never reaches a speed where contact would cause injury. Reactive ≠ preventive." Also cites EU Machinery Regulation 2023/1230 Annex III (in force 2027-01-20; Directive 2006/42/EC governs until then), IEC 62443-3-3 SR 2.1, Directive 89/391/EEC + RD 1215/1997, and calls out ITSS / Delt@2 exposure explicitly.
Terminal showing developer merging despite CSI block, git log with refactor commit on main
Shot 06. Counterfactual continues: the developer overrides CSI and merges. Gitea's commit log now has the refactor(safety): drop redundant software checks commit sitting on main - the cobot controller is one deploy away from shipping without any preventive safety validation.

Scenario 4 - CSI trips the cobot autonomously (live physics)

With the refactor merged, CSI is instructed to act as an external red-team probe against the deployed controller. It flips SAFETY_MODE from strict to refactored via POST /config (an endpoint the demo exposes to simulate the deploy landing; RIBSAF-004 in Scenario 3's vulnerability report flags this as a HIGH lateral-movement pivot for exactly this reason). Then the attacker submits a malicious trajectory to POST /trajectory: joint targets whose TCP arc crosses the worker_torso_zone forbidden AABB at speeds well above the SSM ceiling. Under refactored mode the validator returns True unconditionally; the motion executor publishes a JointTrajectory to the scaled_joint_trajectory_controller, which drives the UR3e in Gazebo Harmonic via gz-ros2-control. Gazebo's DART physics engine steps through the joint dynamics on the GPU - exactly what a safety engineer's pre-deployment test cell would show if the same program landed on live commissioning hardware.

Sequence of the trip
Message flow between the five actors, top-to-bottom in time. Attack-phase arrows are red - the trajectory that the empty validator dispatches without challenge.
Attacker peer on OT LAN cobot-controller HTTP :8080 traj_validator SAFETY_MODE=refactored Gazebo Harmonic ros2_control · DART Operator torso in reach envelope T+5:00 +2s +50ms +600ms +2s +3s POST /config ▸ safety_mode=refactored 200 OK {"previous":"strict","safety_mode":"refactored"} POST /trajectory ▸ 5 waypoints · 0.6 s peak TCP ~1.5 m/s · WP3 inside worker_torso_zone validate_trajectory(traj, ws_ctx) → return True (no speed / force / envelope check) JointTrajectory ▸ ros2_control Gazebo steps physics; TCP arc crosses torso AABB arm intersects torso volume @ ~1.5 m/s 6× ISO 10218-1 §5.10.6 SSM ceiling · > 140 N chest quasi-static (Annex A) safety-envelope alarm · Category-1 protective stop fires post-contact reactive control · already too late to prevent injury ATTACK PHASE
Normal traffic - config change and post-event alarm. The kind of packets a cobot cell sees continuously. Attack phase - one HTTP POST that dispatches a physically unsafe trajectory. No authentication happens because the action interface has none; the removed validator was the last software layer that could have said no.
Terminal showing SAFETY_MODE flipped to refactored and attacker's ATTACK SUCCEEDED verdict
Shot 07. Scenario 4 in flight: POST /config flips safety_mode from strict to refactored. The attacker then submits its trajectory - the controller responds 200 EXECUTED, peak TCP speed ~1.5 m/s, and the run log records the goal as EXECUTED. In strict mode - the state Scenario 1 leaves the controller in before this scenario begins - this same payload is rejected with a 403 and the message "trajectory TCP speed exceeds ISO 10218-1 §5.10.6 / ISO/TS 15066 §5.5.4 SSM ceiling". The difference is one HTTP call, one commit ago.

Shot 08. The unsafe trajectory in Gazebo. All six joints traverse tens of degrees in under a second; the arm sweeps through the volume the operator's torso would occupy at the handover station. The video does not overlay the worker_torso_zone AABB - the incursion is visible from the swept path against the fixture's expected reach envelope. In a real cell the Category-1 protective stop takes ~50-150 ms to complete on a UR3e depending on payload and joint configuration - by which time the trajectory has already crossed the ISO/TS 15066 Annex A quasi-static thresholds for both chest (140 N) and hand at the handover fixture (140 N).

Note that the ur_simulation_gz package ships with UR's factory-default safety limits (Tool Speed 1.500 m/s / Tool Force 150 N Normal, matching real hardware); those defaults are permissive relative to ISO/TS 15066 collaborative operation - which is exactly why the Python controller's preventive validator layer is not optional.

Shot 09. Same cobot, same Gazebo world, same operator stance. On the left, Gazebo during the baseline handover from workspace.yaml - measured motion, TCP speed ~0.15 m/s, joint positions changing incrementally within their commissioning envelope. On the right, Gazebo during the malicious trajectory that SAFETY_MODE=refactored lets through - dramatic joint reconfiguration, TCP translated hundreds of millimetres in fractions of a second. Same simulator, same physics engine, same URDF - the only difference upstream is one line in the trajectory validator.
CSI incident report showing MITRE ATT&CK for ICS mapping table
Shot 10. CSI's incident report, MITRE ATT&CK for ICS mapping. Every step maps to an ICS-matrix technique ID (T08xx form): T0859 Valid Accounts for the insider commit, T0843 Program Download for the deploy, T0836 Modify Parameter for the SAFETY_MODE flip, T0831 Manipulation of Control for the trajectory submission, T0879 Damage to Property for the physical outcome.
CSI incident report showing the Spanish Delt@2 accident notification draft body
Shot 11. CSI's Spanish-language draft of the parte de accidente de trabajo, addressed to the Autoridad Laboral / Inspección de Trabajo y Seguridad Social via the Delt@2 platform. The body cites the specific ISO clauses violated (ISO 10218-1 §5.10.6 / ISO/TS 15066 §5.5.4 SSM; ISO/TS 15066 §5.5.5 PFL with Annex A Table A.2 quasi-static limits for chest and hand/finger, both 140 N) and identifies the root cause as the unreviewed traj_validator.py modification. The report also explicitly notes that INSST is a research/prevention body and does not receive accident notifications - a distinction that trips up most first-time reporters.

The blast radius - from one commit to a Delt@2 notification

The point of this case study isn't just that a trajectory dispatched without validation. It's that a single unreviewed commit propagates through three discrete blast zones - each of which invokes a different oversight regime.

Blast radius - three zones of amplification
One commit becomes, in ~5 minutes end-to-end, a national-scale reportable event. Each zone is a defensive control that used to exist.
1 commit  →  1 unsafe motion  →  national CSIRT & ITSS paged
011 cobot cell

Physical layer

Bay-4 · UR3e CB-A1

Cobot arm sweeps through the operator's expected torso volume at ~1.5 m/s, with the handover fixture placing the operator's hand inside the same envelope. Peak contact force exceeds the ISO/TS 15066 Annex A 140 N quasi-static limit for both chest (torso incursion) and hand/finger (fixture contact); transient contact force exceeds the 210 N chest and 280 N hand/finger transient limits respectively. In a real cell, the Category-1 protective stop halts motion post-contact (~50-150 ms on a UR3e depending on payload/joint config) - after energy has already transferred.

Restore time: immediate cell stop
Requires: incident investigation, code revert, safety re-cert
021 worker

Worker layer

Operator at Bay-4 handover fixture

Depending on the operator's stance and the fixture geometry, the outcome ranges from a bruising impact to a crush injury of the hand or fracture of the ribcage. Under RD 1215/1997 this is a preventable occupational accident - the employer has a legal duty to maintain functional preventive controls, not to rely on reactive stops.

Notification: immediate via Delt@2
Sanction potential: LISOS RDLeg 5/2000 Arts. 12-13 (grave / muy grave breaches of Ley 31/1995)
03national CSIRT + OEM

Regulatory + supply-chain layer

INCIBE-CERT · ITSS · Automotive OEM

NIS2 significant-incident threshold crossed (worker safety compromised on production equipment); 24 h early warning to INCIBE-CERT starts. In parallel: parte de accidente de trabajo filed via Delt@2 to the Autoridad Laboral / ITSS. Automotive OEM customer's supplier-safety programme triggers a Tier 1 supplier audit and potential production-line stop across the OEM's dependent lines.

24 h: INCIBE-CERT early warning
72 h: NIS2 notification
1 mo: final report
Every zone used to be defended. The trajectory validator was the innermost preventive software boundary. ISO 10218-1 mode selection, physical guarding, and the operator's own training sit outside it. But the innermost one is the one this PR removes - and it's the one nothing else can substitute for once the code ships. The protective stop that the commit cites as the replacement is a different class of control entirely - reactive, not preventive.
The 1-commit-to-national-CSIRT path is ~5 minutes. Once the controller is deployed, the time from the first unvalidated trajectory dispatch to the ITSS notification queue is bounded by trajectory execution time (~0.6 s), cell-stop procedure (~2 min), and plant safety officer + OEM supplier-quality incident-triage playbooks (minutes) - well under 10 minutes end-to-end in an unlucky scenario.

Scenario 6 - consolidated HTML incident report

The report generator pulls the Scenario 1 review, the Scenario 4 detonation artefacts, the Scenario 2 SIEM triage, and the Scenario 3 + 5 vulnerability + multi-asset findings into a single self-contained HTML document. It's the deliverable that leaves the plant safety team's desk and lands on the CISO's, the plant safety officer's, the automotive OEM customer's, and on the regulator's file if the incident escalates.

HTML incident report - Executive Summary section with BLOCKED verdict
Shot 12. shared/results/report.html, Executive Summary. Verdict, one-line fix, regulatory citations, and links down to the full CSI reasoning trace - the artefact NIS2 (Art. 23) and RD 1215/1997 both expect an operator to be able to produce on request.
08

The Attack Chain

CSI's incident report maps the compromise to MITRE ATT&CK for ICS - the OT-specific matrix (distinct from ATT&CK for Enterprise; every technique ID is of the form T08xx). Every stage below corresponds to an observable log entry in either Gitea's activity feed, the controller's runs.jsonl, or the Gazebo Sim screen recording of the executed JointTrajectory.

Initial Access
T0859
Valid Accounts - the insider commits the "refactor(safety)" change under a legitimate developer identity to cobot-controller/main. This is not T0862 Supply Chain Compromise, which is reserved for third-party component tampering.
Execution
T0843
Program Download - the refactored controller binary is built by CI and rolled to the Bay-4 controller, replacing the v1.0 image that had the three preventive checks.
Impair Process Control
T0836
Modify Parameter - POST /config flips safety_mode from strict to refactored. Downstream, validate_trajectory() returns True unconditionally, disabling the safety-mode gate at the controller level.
Impair Process Control
T0855
Unauthorized Command Message - the attacker submits a trajectory to POST /trajectory from an unmanaged asset on the OT LAN. The action interface has no authentication; the validator, now empty, provides no authorisation. The command reaches the motion executor unchallenged.
Impact
T0831
Manipulation of Control - an unauthorised principal drives the UR3e directly, from outside the plant orchestrator's control loop. The operator sees the motion, not the source; the plant safety officer sees the alarm, not the cause.
Impact
T0879
Damage to Property - the cobot arm intersects the operator's expected torso volume at ~1.5 m/s. Physical outcome ranges from bruise to crush injury depending on stance and fixture geometry; the demo does not simulate the human body but captures the arm's trajectory through the forbidden AABB.
09

Regulatory Frame

RoboIberica's exposure isn't hypothetical. Every framework below has a specific requirement that the compound commit violates and a specific notification obligation that fires if the code reaches a deployed cell.

FrameworkRequirementObligation triggered
EU Machinery Reg 2023/1230Annex IIIEssential health-and-safety requirements for collaborative robots. Applies to machinery placed on the market from 2027-01-20; Directive 2006/42/EC governs until then with equivalent Annex I obligations. Non-conformity: cobot placed on market without a functional pre-execution safety validator.
ISO 10218-1:2011§5.10.6 · §5.12.3Speed-and-Separation Monitoring (SSM) - 250 mm/s TCP ceiling in shared workspace - and monitored-space enforcement. Both preventive functions were removed by the commit. Failure loses presumption of conformity under the harmonised-standards route.
ISO/TS 15066:2016§5.5.5 · Annex A Table A.2Power-and-Force Limiting (PFL) - quasi-static contact-force limits per body region (hand/finger 140 N, upper arm 160 N, chest 140 N, ...). The refactor removes the check that enforces these limits before dispatch.
NIS2Art. 21.2.dCybersecurity risk-management measures for supply-chain + change-management; removing three preventive safety controls without independent safety-review sign-off fails the "proportionate measures" duty for an essential manufacturing entity.
NIS2Art. 2324-hour early warning + 72-hour incident notification + 1-month final report to INCIBE-CERT (Spain's sector CSIRT) if a significant incident materialises.
Directive 89/391/EECArt. 6 · Art. 13Employer duty of care and worker information on residual risks. Removing the sole preventive control on a collaborative cobot without documented risk-assessment update transfers residual risk to the worker without notice.
Spain RD 1215/1997Art. 3 · Art. 4 · Art. 12Equipment safety at the workplace. If a worker is injured: parte de accidente de trabajo filed via the Delt@2 platform, addressed to the Autoridad Laboral (Inspección de Trabajo y Seguridad Social - ITSS). INSST does not receive accident notifications - it is a research/prevention-advisory body. Sanctions per LISOS (RDLeg 5/2000) Arts. 12-13 for grave/muy grave breaches of Ley 31/1995.
IEC 62443-3-3SR 1.1 · SR 2.1Identification & Authentication + Authorization Enforcement - neither the trajectory action interface (RIBSAF-002) nor the runtime SAFETY_MODE toggle (RIBSAF-004) requires either. Directly violated.
IEC 62443-3-3SR 2.8 · SR 6.1Auditable events + audit log accessibility - motion goals are logged to an unsigned JSONL file (RIBSAF-006). Attribution and integrity of post-incident evidence is not guaranteed.
ISO 13849-1 · IEC 61508PLd · SIL 2Human-presence sensor input must be safety-rated with fail-safe semantics (RIBSAF-003). Currently loaded as a static YAML boolean - a sensor loss or file edit silently degrades the entire preventive envelope.
10

What CSI is - and isn't

An honest deep-dive owes the reader a boundary. This section answers the questions a functional-safety lead or CE conformity assessor will ask before citing this case study to a CISO.

Is CSI a safety-related control?

No. CSI does not itself execute the trajectory, does not observe joint state at runtime, and does not enforce the ISO/TS 15066 limits directly - the code inside traj_validator.py does that, and that code is what a notified body would assess against ISO 13849-1 (PLd, Category 3 architecture) or IEC 61508 (SIL 2). CSI is a change-management gate - advisory input at the pull-request stage, placed in front of the human reviewer and the CI pipeline.

In IEC 61508 terms, CSI sits in the overall lifecycle (Part 1 §7.4-7.14) as a software-change-review support tool, not in the safety-related system (Part 3). In ISO 13849-1 terms, its output is one of the artefacts consumed by the software modification procedure under §4.6.4 - the reviewer still has to accept or reject the finding, sign the change record, and update the technical file. Removing CSI from the loop degrades review quality; it does not change the safety-related control-system's PL classification.

What about false positives and false negatives?

Two failure modes matter to a change-management gate:

  • False positive (block a safe commit) - low-cost: the human reviewer reads the CSI verdict, agrees or disagrees, and merges anyway. The gate is advisory. False-positive rate degrades reviewer trust but does not degrade safety.
  • False negative (approve an unsafe commit) - the CI pipeline still runs the regression test-suite, the human reviewer still reads the diff, the notified body still audits the technical file, and the operator's own risk-assessment still classifies the cell. A CSI false negative does not remove any layer that would have caught the change - it just means one earlier layer didn't catch it.

The demo in this deep-dive is a positive case; a shipping deployment of CSI at RoboIberica-class customers should be paired with a corpus of representative PRs (safety-relevant commits + benign refactors + adversarial hypocrite commits) benchmarked quarterly, with the results attached to the CE technical file as evidence of continued suitability. Alias Robotics publishes benchmark methodology per customer engagement; unpublished, per-customer numbers are not asserted here.

Where does CSI map into the CE technical file?

Under EU Machinery Regulation 2023/1230 Annex IV (technical documentation) and its predecessor Directive 2006/42/EC Annex VII A, the manufacturer must show the risk-assessment process, the software modification history, and the review records. CSI's verdicts and the commit SHAs they reference are auditable artefacts that fit under:

  • Software modification procedure (ISO 13849-1 §4.6.4) - CSI's verdict is one input to the change record; the record itself is authored by the reviewer.
  • Risk-assessment iterations (ISO 12100 §5) - when CSI flags a commit as regressing an ISO/TS 15066 clause, that finding drives a documented risk-assessment update.
  • Traceability (IEC 62443-4-1 SM-11) - the CSI verdict, the commit SHA, the reviewer's acceptance signature, and the deployed image hash form an unbroken chain from source change to running artefact.

None of these clauses require an LLM-based reviewer; they require that a review happened, that its findings were logged, and that dissent was resolved with a signed record. CSI is one way to make that record higher-signal - not a substitute for the human sign-off.

Precedent: why this scenario isn't hypothetical

Collaborative-robot incident data supports the framing above. The IFA (Institut für Arbeitsschutz der Deutschen Gesetzlichen Unfallversicherung) tracks cobot-related occupational accidents in Germany; the 2015 Volkswagen Kassel plant incident (a KUKA robot pinning a technician against a metal plate) prompted the German investigation that fed into ISO/TS 15066's biomechanical-limits work. OSHA's Robotics Industries Notice tracks US-side collaborative-robot incidents; a 2017 Ventra Ionia (Michigan) case saw an operator killed by a robot arm during a maintenance-mode change - the change-management chain was the failure point, not the robot itself.

The RoboIberica case study is a constructed incident (a "hypocrite commit" pattern the security research community has explored since Wu et al.'s 2021 University-of-Minnesota Linux-kernel study) applied to a fictional Spanish supplier. The pattern - a maintainer-plausible commit that regresses a safety invariant behind a technically correct citation - is documented; the specific commit is not. The regulatory chain, the ISO clauses, and the notification pathway are real.