Is Class 9 (Script Table) Dynamic Behavior Orchestration a Security Vulnerability or an Advanced Edge Feature?
-
[!WARNING]
Technical Redaction & Safe Harbor Notice:
All communication captures, system titles, and cryptographic parameters in this thread have been sanitized and neutralized. Real utility meter identifiers, production encryption keys (GUEK/GAK/MK), SIM IMSIs, and proprietary network envelopes have been substituted with standard IEC 62056 synthetic test vectors. Do not post unredacted production captures or live cryptographic keys.In our next-generation AMI architecture, we want to implement demand-response and automated load-limiting directly at the meter edge without requiring full OTA firmware updates (Class 18). Conceptually, DLMS/COSEM Class 9 (Script Table) provides a declarative execution AST where complex multi-step sequences can be chained together.
We attempted to dynamically register a custom script (Script ID
99) into the Disconnect Control Script Table (Class 9, OBIS0-0:10.0.106*255). This script was designed to chain two sequential actions: (1) Execute Class 70 Method 1 (remote_disconnect), and (2) Write an alarm status bit into Class 1 (OBIS0.0.96.11.0.255, Attribute 2).We transmitted the following sanitized
Set-Request-NormalAPDU targeting Attribute 2 (scripts) over an authenticated Management Association (Client SAP0x0001, HLS 5 GMAC):00 01 00 01 00 01 00 29 C1 01 C1 00 09 00 00 0A 00 6A FF 02 00 01 01 02 02 12 00 63 01 02 02 05 16 01 12 00 46 09 06 00 00 60 03 0A FF 0F 01 0F 00 02 05 16 02 12 00 01 09 06 00 00 60 0B 00 FF 0F 02 03 FFDissecting the payload structure:
C1 01 C1:Set-Request-Normal, Invoke-ID100 09: Class ID9(Script Table)00 00 0A 00 6A FF: OBIS0-0:10.0.106*25502 00: Attribute2(scripts), no selective access01 01: Array of 1 Script02 02: Structure of{ script_id, actions }12 00 63:script_id = 99(long-unsigned)01 02: Array of 2 Actions- Action 1:
service_id = 1(Action),class_id = 70, OBIS0.0.96.3.10.255, Method ID1(remote_disconnect), param0 - Action 2:
service_id = 2(Write),class_id = 1, OBIS0.0.96.11.0.255, Attr ID2, value0xFF
However, the meter firmware categorically rejects this SET request with
read-write-denied(0x03
00 01 00 01 00 01 00 04 C5 01 C1 03Why do meter vendors lock Class 9 Attribute 2 as read-only if the DLMS UA specification defines it as a configurable table for client-defined automation?
-
Marcus, allowing remote clients to dynamically inject executable action graphs into Class 9 is not just an extensibility choice—from a cryptographic and legal metrology standpoint, it represents a critical security vulnerability.
Look closely at what your SET payload accomplishes: you are embedding a remote method dispatcher inside the meter's internal event loop. If Class 9 Attribute 2 were dynamically writable over the air, an attacker with compromised low-level credentials could construct an arbitrary action sequence—for instance, chaining an innocuous clock synchronization event or optical probe connection to trigger Class 70 (
remote_disconnect) or Class 7 (Profile Genericreset).Under international legal metrology requirements (such as WELMEC Software Guide 7.2 under the Measuring Instruments Directive MID 2014/32/EU and OIML R46 Section 6.3

- All executable control paths affecting physical actuators (relays, valves) and legally relevant billing registers must be strictly separated and immutably verified during type certification.
- Dynamic construction of execution call graphs post-production violates the non-influenceability requirement of legal software.
Furthermore, per DLMS UA Green Book 10th Ed Section 9.3.4, Method Access Rights in the
Association LNobject (Class 15) are evaluated per individual client association. If a client could inject an Action into Class 9 that invokes Class 70 Method 1, and then bind that script to a low-privileged Class 22 Single Action Schedule, it would effectively bypass the association's method access control matrix.This is why every certified DLMS smart meter mandates that Class 9 Attribute 2 is strictly read-only.
-
Alex is spot on regarding legal metrology and security boundaries. If we examine the data model defined in DLMS UA Blue Book (17th Ed.) Section 4.5.2 (Class ID 9: Script Table) and IEC 62056-62:2019 Clause 4.5.2, the specification explicitly accounts for this distinction.
Per Blue Book Section 4.5.2, each script entry in Attribute 2 is defined as:
script ::= structure { script_identifier : long-unsigned, actions : array of action_specification } action_specification ::= structure { service_id : enum (1: action, 2: write), class_id : long-unsigned, logical_name : octet-string, index : integer8, parameter : choice }In standard metering architecture, the DLMS User Association standardizes well-known pre-compiled Script Tables with fixed Script IDs:
0-0:10.0.106*255: Disconnect Control Script TableScript 1: Invokes Class 70 Method 1 (remote_disconnect)Script 2: Invokes Class 70 Method 2 (remote_reconnect)
0-0:10.0.0*255: Global End-of-Billing-Period Script TableScript 1: Invokes Class 7 Method 1 (reset) on billing profile
Rather than treating Class 9 as a runtime programmable virtual machine or script interpreter, embedded meter firmware implements Attribute 2 as a static
constarray compiled directly into Flash/ROM. The table acts as a Command Registry, not a user-definable macro editor.To perform multiple actions (e.g. disconnecting the load and asserting an alarm flag), the HES must execute the certified discrete methods individually, or trigger a factory-provisioned composite script ID.
-
From an embedded firmware perspective, Sarah and Alex have explained the core design reality. Storing dynamic script trees on an ultra-low-power MCU would require a dynamic expression parser, variable-length buffer managers, and deep stack-unwinding protection against recursive script loops.
Instead of attempting to write Attribute 2, the standard-compliant way to use Class 9 is to read the pre-configured script catalog, and then invoke Method 1 (
execute) with the desiredscript_identifier.Here is the verified readback of the factory-provisioned Disconnect Script Table (
0-0:10.0.106*255, Attribute 2):00 01 00 01 00 01 00 2A C4 01 C1 00 01 02 02 02 12 00 01 01 01 02 05 16 01 12 00 46 09 06 00 00 60 03 0A FF 0F 01 0F 00 02 02 12 00 02 01 01 02 05 16 01 12 00 46 09 06 00 00 60 03 0A FF 0F 02 0F 00Dissecting the meter's pre-compiled table:
- Script ID
1(12 00 01
Action on Class 70(0x0046), OBIS0.0.96.3.10.255, Method ID1(remote_disconnect) - Script ID
2(12 00 02
Action on Class 70(0x0046), OBIS0.0.96.3.10.255, Method ID2(remote_reconnect)
And here is the verified working
Action-Request-NormalAPDU to execute Script ID1(Remote Trip) via Class 9 Method 1 (execute
00 01 00 01 00 01 00 12 C3 01 C2 00 09 00 00 0A 00 6A FF 01 01 12 00 01Meter response (
Action-Response-Normal, success):00 01 00 01 00 01 00 05 C7 01 C2 00 00Here is the clean Gurux.DLMS Python snippet illustrating standard Script Table execution:
from gurux_dlms.objects import GXDLMSScriptTable def execute_meter_script(client, obis_code, script_id): script_table = GXDLMSScriptTable(obis_code) # First read Attribute 2 to verify available script selectors client.read(script_table, 2) # Verify that requested script_id exists in the certified table script = next((s for s in script_table.scripts if s.id == script_id), None) if not script: raise ValueError(f"Script ID {script_id} not supported by meter firmware.") # Invoke Method 1 (execute) with script selector parameter (long-unsigned) return client.method(script_table, 1, script_id, "long-unsigned")Respecting Class 9 as an immutable command registry ensures compliance with MID/WELMEC metrology while providing fully predictable remote execution.
- Script ID
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login