Note
What a station checks before loading a module
Signing is not a formality bolted on at the end. It is a load-time gate whose default refuses unsigned code — and some permissions are checked whatever the setting says.
- Module signing
- Certificates
- Deployment
The mode values
A Niagara host decides how strict to be about module signatures with a single
system property, niagara.moduleVerificationMode. It takes four
values — three real settings and one that means "nobody chose" — and the
distinction between the three is about the certificate, not about whether
a signature exists.
| Mode | What the host requires |
|---|---|
| low | Warnings only — an unsigned module still loads. Documented as an option that will be removed in a future release, so anything depending on it has a deadline whether or not anyone has written it down. |
| medium | The current default. Modules must be signed by a valid, trusted certificate. Trusted means present in that host's trust store — which is a per-host fact, not a property of your certificate. |
| high | Valid, trusted and CA-issued. An internal CA is acceptable, so this does not automatically mean buying a certificate, but it does rule out a bare self-signed key. The rule covers the timestamp as well as the signature: a lone self-signed certificate in either path is refused, and the message names which one. |
There is a fourth value, noPreference, which is what the setting means
when nobody has chosen: the host resolves it from its own version. Below 4.8 the
mode is forced to low whatever the preference says, 4.8 resolves to low, and 4.9
and later resolve to medium. noPreference is not a way to opt out —
it inherits whatever the running version's default happens to be.
Default is medium, and that is the number that matters. An unsigned module does not install on a stock station or a stock controller. Not "warns", not "logs" — refused.
Medium became the default in Niagara 4.9
The default moved in two steps, not one. Niagara 4.8 shipped with the verification mode at low; 4.9 raised the shipped default to medium. A host running 4.9 or later gets medium behaviour out of the box. A host still on 4.8 does not — which is why a jar that installed unsigned for years stops installing the moment the host is upgraded, with no change to the jar itself.
Some permissions demand a signature whatever the mode says
The mode is not the only gate. Before it looks at the setting at all, the host asks whether the module requests a Niagara permission that requires a signature — and if it does, the signature is checked even on a host set to low. Six permission groups carry that requirement: access class, HSM signing, MBean, protection domain, reflection and third-party permission. Five are rated severe risk; protection domain is rated mild.
Reflection and third-party permission are the two that ordinary driver code reaches
for. A module that wraps a vendor SDK, or that reads a private field to get at
something the public API does not expose, is in signature territory regardless of
what the estate has set. Unsigned, it is refused with failed signature
validation: Module not signed, naming the module part that failed — so an
unsigned -ux jar can be rejected while the -rt jar beside
it loads. The wording is worth reading closely when a log line is all you have: the
not-signed and invalid-signature messages name the module, while a
certificate-chain failure names the module part — the name
attribute from module.xml, profile suffix included. Same check, two vocabularies,
and only one of them tells you which jar to look at.
There is a quieter failure in the same area. The permission groups a module requests are parsed one by one, and when a group that requires a signature is found in an unsigned jar the parser raises Permission group … requires signature but the module … is not signed — which is then caught in the same loop, logged as a warning about XML that could not be parsed, and the element is skipped. The module still loads. It simply loads without that permission, and the first symptom is a security exception in whatever code needed it, at a point far away from the cause. On an unsigned development build, a missing permission and a broken feature look identical.
The installer checks before the station ever sees the jar
Everything above is load time, inside the station. Software Manager and the
commissioning wizard run their own check first, and it resolves the mode from the
target, not from the workstation doing the installing: the platform's own
preferred mode, combined with the version of the baja module on that
host. Engineer a 4.8 controller from a 4.15 Workbench and the install-time rule is
the controller's, not yours.
The installer also grades a signature more finely than the station does. It classifies each jar into one of nine states — fine, unsigned, invalid signature, not timestamped, unknown, self-signed signer, self-signed timestamp, chain validation failure, chain validation warning — and then asks whether that state is acceptable in the resolved mode. Low rejects only an invalid signature. Medium adds unsigned, chain-validation failure and unknown. High adds the two self-signed cases. Two states are acceptable in every mode, including high: not timestamped, and a chain-validation warning. A signed module with no timestamp installs everywhere — which is convenient right up to the day the signing certificate expires, because without a timestamp there is nothing to prove the signature predated the expiry.
One boolean on the engineering workstation turns the install-time check
down to low. niagara.commissioning.ignoreVerificationMode is
read in the installing process, and unlike the verification mode itself it is not on
the runtime's denylist of properties that cannot be passed as launch arguments. It
does not weaken the station's own load-time gate — but it does mean "it installed
fine on my machine" is not evidence that a jar would install on a properly
configured host.
Trusted is a property of the host
The most common surprise is a module that installs on one host and is refused by the next, with the same jar and the same signature. Nothing about the module changed; the second host does not have the signing certificate in its trust store.
This is why "is it signed?" is the wrong question when something will not install. The question is "is this certificate trusted by this host, and does this host demand a CA behind it?" The answer is per host, and on an estate assembled over several years the answer varies across the estate.
You cannot talk a station out of it at the command line
There is a matching denylist of properties that cannot be set as launch arguments, and the verification mode is the first entry in it, alongside the program-object signing property. The default list is compiled into the runtime, so it applies to a host whose configuration file says nothing about it.
The enforcement has one condition worth knowing. It applies to a user who cannot
write the host's system.properties: their -D is discarded
and a warning is logged. Someone who administers the host and can edit that file can
still change the setting there — deliberately, in configuration, where it is visible
and auditable — but a process cannot quietly lower it for itself on the way up.
Treat a plan that involves relaxing verification as a plan that will be rejected during commissioning.
Program objects are gated separately
Modules are not the only executable thing in a station. Program objects have their own signing requirement, with its own property, defaulting to permissive — unsigned program objects run. A site that has tightened module verification and left program objects alone has a gap it very likely does not know about, and closing it is a one-line configuration change plus the work of signing what is already there.
Practical consequences
- Sign in development, not at the end. A build that produces unsigned jars for months and signs once before delivery discovers every trust and packaging problem on the day of delivery.
- Decide self-signed or CA early. Self-signed with the certificate distributed to the estate's trust stores is coherent for an internal estate. Anything sold or shipped to third parties needs a CA behind it, and obtaining a code-signing certificate now requires hardware key storage — which takes lead time and money, so it belongs in the plan, not the last week.
- Record which certificate signed which release. When a certificate expires or is replaced, the question "what is out there signed by the old one" needs an answer that is not an estate-wide search.
The modes, the signature states each one accepts, and the log lines quoted above are
all read out of the shipped jars by
module-sign-scan, which is free
and MIT. Run it against the installation you are shipping to and the answer is that
installation's rather than this page's.
Sources
Where this is written down
- The jarsigner Command, JDK 25 tool specification — What signing a jar consists of, and what -verify reports, independently of any Niagara-specific verification mode
Related
Where this comes up in the work
Custom modules & drivers
Bespoke Niagara rt, wb and ux modules and drivers written against the Baja API: pure Java, signed, and stamped to install across a mixed estate.
Station engineering
JACE controller and Niagara station setup end to end: platform commissioning, TLS, users, roles, BACnet and Modbus, tagging, histories, alarms, backups.
More notes
Other things worth writing down
The certificate on a new JACE
Every station starts with a self-signed certificate it generated itself. What that is good for, what it is not, and what breaks on the day it expires.
- TLS
- Certificates
- Commissioning
Commissioning a JACE-8000 without locking yourself out
The factory address, the passphrase with no recovery path, and the account you are made to delete — the Niagara 4 steps that strand a new controller.
- JACE
- Commissioning
- Deployment
The http redirect a static host does not add for you
A host that serves https does not always redirect plain http to it. What a plain-http request really does, and the one-line fix on four common hosts.
- https
- Static hosting
- Deployment
Next step
Tell us the version, the hardware, and what it has to do.
You will get a written scope and a fixed price against it. If the honest answer is that you do not need us, you will get that instead.