-
Notifications
You must be signed in to change notification settings - Fork 19
ScriptSigning
Outset 4.3.0 introduces Ed25519 asymmetric signing as the preferred method for verifying script integrity before execution. It replaces the SHA256 checksum feature, which is deprecated as of 4.3.0.
An admin generates an Ed25519 keypair. The private key stays on the admin workstation and is used to sign scripts. The public key is deployed to managed devices via MDM as the manifest_signing_key preference.
Each script carries its own signature embedded as a comment:
# ed25519: <base64-encoded-signature>
When Outset runs and manifest_signing_key is present, it verifies this comment against the script content before executing. Scripts without a valid signature are refused.
The SHA256 checksum approach requires maintenance of an MDM profile whenever a script is modified. This can present friction in using the feature effectively.
With Ed25519:
- The private key is never on the device — it cannot be stolen or misused from a compromised machine.
- The public key on device can only verify, never forge. An attempt to modifies a script cannot produce a valid signature without the private key.
- Each script is self-contained: the signature travels with the file and can be tracked in version control.
/usr/local/outset/outset --generate-keypairOutput:
Ed25519 signing keypair generated.
Private key (keep secret — used to sign scripts):
<base64-private-key>
Public key (deploy via MDM as 'manifest_signing_key'):
<base64-public-key>
Store the private key securely (password manager, secrets vault, etc.). It is never needed on a managed device.
Add the following to your Outset configuration profile:
<key>manifest_signing_key</key>
<string>BASE64_PUBLIC_KEY</string>Security note:
manifest_signing_keyis only honoured when it is MDM-managed (i.e. delivered in a managed profile). If the key is present in/Library/Preferences/but not managed, Outset ignores it and logs an error. This prevents a local admin from writing a bogus key to silently block script processing. In--debugmode a locally set value is accepted to allow testing without an MDM enrolment.
/usr/local/outset/outset --sign-script-file /path/to/script.sh --signing-key <base64-private-key>Multiple files can be signed in one invocation:
/usr/local/outset/outset \
--sign-script-file /path/to/a.sh \
--sign-script-file /path/to/b.sh \
--signing-key <base64-private-key>The command embeds a # ed25519: <sig> comment in each file, inserting it after the shebang line if one is present.
For scripts delivered as MDM payloads, sign the script file before base64-encoding it for the payload:
/usr/local/outset/outset --sign-script-file my-script.sh --signing-key <base64-private-key>
base64 -i my-script.shThe embedded signature comment is preserved in the base64-encoded content and verified when Outset decodes and runs the script.
Once signed, deploy scripts to the appropriate /usr/local/outset/ directory as normal. The signature travels with the file.
Outset verifies each script automatically before execution whenever manifest_signing_key is configured. No extra steps are required.
To verify a script without executing it:
/usr/local/outset/outset --verify-script /path/to/script.sh --public-key <base64-public-key>Multiple files:
/usr/local/outset/outset \
--verify-script /path/to/a.sh \
--verify-script /path/to/b.sh \
--public-key <base64-public-key>Output per file is <path>: OK or <path>: INVALID. The process exits non-zero if any file fails, making it suitable for use in CI pipelines or pre-deployment checks.
The signature is embedded as a #-prefixed comment, so signing works with any scripting language that treats # as a line comment: shell (sh/bash/zsh), Python, Perl, Ruby, and similar. These cover the overwhelming majority of Outset scripts in practice.
Swift scripts are not supported. Swift source files use // for comments; a bare # line (outside of a shebang) is a compile error. Signing a .swift script will cause it to fail at execution. Admins who need tamper protection for Swift scripts should use the SHA256 checksum mechanism or wrap the Swift invocation in a shell script that can carry the signature.
The signed payload is the script content with any existing # ed25519: line stripped out. This means:
- Re-signing a script (e.g. after rotating keys) produces a new valid signature without accumulating multiple comment lines.
- You can inspect, diff, and version-control a script with or without its signature comment — the canonical content is the same either way.
To rotate the signing key:
- Generate a new keypair with
--generate-keypair. - Re-sign all scripts with the new private key using
--sign-script-file. - Update the
manifest_signing_keypreference in your MDM profile with the new public key. - Deploy updated scripts and updated profile together.
Outset will reject scripts signed with the old key once the new public key is deployed, so ensure all scripts are re-signed before pushing the profile update.
Deprecation notice: The
sha256sumchecksum feature is deprecated as of Outset 4.3.0. It will receive no further maintenance and will be removed in a future release. New deployments should use Ed25519 signing instead.
If you are currently using sha256sum verification, the migration path is:
- Generate a keypair and deploy the public key via MDM as described above.
- Sign all scripts currently covered by
sha256sumentries using--sign-script-file. - Remove the
sha256sumkey from your MDM configuration profile.
Both mechanisms can coexist during a transition period: Outset checks checksums (if sha256sum is present) and signatures (if manifest_signing_key is present) independently. A script must pass whichever checks are active.