Skip to content

Scripting

The script library is where your team keeps the scripts it runs on endpoints. A script is written once, approved, and then run on any number of endpoints, on demand or on a schedule, with every run recorded. Approval signs the script, and the signature is what an endpoint checks before it runs anything unattended. This page explains the parts of the library and the rules that decide whether a script runs.

To add a script, see Write and approve a script. To run one, see Run scripts on endpoints.

Scripts > Library lists every script you can run. Each row shows which library the script belongs to:

ChipMeaning
Built-inShipped with Outpost. Read-only, and offered to every client. See Built-in script library.
This client onlyStored in this client’s own data. No other client can read it.
Every clientStored once in your shared library and offered to every client you manage. MSP plan only.

On the MSP plan, a new script written inside a client’s workspace asks Who can use this script: This client only or Every client. You can move a script between the two later with Move…. A move keeps the script’s id, version numbers, and history, so schedules and past runs that name it keep working. A move needs both script:manage and script:approve, because it changes which clients can see and run the script.

On Home Lab, Essentials, and Enterprise there is one client, so every script you write belongs to it, and the shared library holds only the built-in scripts.

A client’s own script can have the same name as a shared one. The chip is how you tell them apart.

InterpreterRuns onAllowed by default
PowerShellWindowsYes
cmdWindowsYes
BatchWindowsNo
shLinux, macOS, FreeBSD, OpenBSDYes
bashLinux, macOS, FreeBSD, OpenBSD, where installedYes
zshLinux, macOS, FreeBSD, OpenBSD, where installedNo
PythonLinux, macOS, FreeBSD, OpenBSD, where installedNo

The profile setting script_execution.allowed_interpreters decides which interpreters an endpoint accepts. Its default is PowerShell, cmd, sh, and bash. To run batch, zsh, or Python scripts, add them to the setting on a profile that applies to the endpoints. An interpreter is allowed only where every applicable profile allows it.

Each script also declares where it Runs on: Any, Windows, Linux, macOS, or BSD. Outpost refuses to run a script on an endpoint whose operating system does not match it or cannot run its interpreter, and the console marks those endpoints with the reason.

A script can declare parameters. Each one has a Key, a Label, a Kind (Text, Number, Checkbox, or Choice), a Default, and whether it is Required. The console asks for the values before each run.

Parameter values are passed to the script as command-line arguments, in the order the parameters are declared. The script body is never rewritten, because its exact bytes are what the approval signature covers. A PowerShell script reads them with a param() block, and a shell script reads them as $1, $2, and so on.

A parameter value can contain these placeholders, which Outpost replaces before the run:

PlaceholderReplaced with
{{endpoint.hostname}}The endpoint’s hostname
{{endpoint.agent_id}}The endpoint’s agent id
{{endpoint.logged_in_user}}The user signed in to the endpoint
{{client.name}}The client’s name
{{site.name}}The endpoint’s site
{{field.<key>}}The endpoint’s value for the custom field with that key
{{login.user}}In a schedule that runs at sign-in only: the person who signed in

A placeholder with nothing to resolve becomes an empty string.

Every script has a version number, starting at 1. Changing the body or the interpreter creates a new version. Changing the name, description, category, tags, or other details does not. History on a script lists every version with when it was written and why, such as Written, Edited, or Copied from another script. Every version is kept, so you can view any one, copy it, or select Start a new draft from this version.

Each run records the version it ran, so a run from last month names the text that actually ran.

A new script, and every new version of one, is a Draft. Approving it, with Approve, signs it with your Outpost’s script-signing key. The signature covers the interpreter and the exact body, so an approved PowerShell script cannot be run as a shell script, and a changed body is not covered.

  • Approving needs script:approve.
  • Changing the body or the interpreter of an approved script returns it to draft and clears its signature. Schedules that use it stop firing until it is approved again.
  • Revoke returns an approved script to draft. Endpoints that require signed scripts then refuse it.
  • Built-in scripts arrive approved.

Before an endpoint runs a script unattended, it checks the signature against your Outpost’s public key. The signature is the one check an endpoint can still make while it is offline and running a schedule from its own copy.

A draft can run only on one endpoint at a time, by a technician with the script:run_unapproved permission. This is how an author tests a script before approving it. A draft cannot run in a batch across several endpoints, on a site or device group, or on a schedule.

The profile setting script_execution.approval_required makes endpoints run a script only once someone other than its author has approved it. It is off by default. Where it applies:

  • A library script runs only if someone other than the author of its current version approved that version. An author who approves their own version does not count. Editing the script needs a new approval.
  • script:run_unapproved does not get around it. A draft cannot run on these endpoints.
  • A script typed at run time, such as on an endpoint’s Commands tab, needs its own approval of its exact text and interpreter, by someone other than the person who asked. That approval lasts 7 days.
  • Scheduled runs of a script without such an approval are skipped on these endpoints, and the run records the reason.
  • A backup pre or post script without such an approval fails the backup run. See Pre and post scripts.

A run that needs approval is refused with This script needs a second person’s approval before it can run on these endpoints., naming the profile that set it.

Asking for approval needs script:manage. Approving and turning down need script:approve.

  • On a script’s page, the Approval card shows who approved it and when, or that it is waiting or was turned down. It offers Ask for approval, Approve, and Turn down. On a library row, Actions has Ask for approval and Turn down.
  • When a typed script is refused for this reason, the run form offers Ask for approval. Approvers see the request under Typed scripts waiting for approval above the library, where they select Approve or Turn down. After it is approved, run the script again.

The person who asked cannot approve or turn down their own request. The console says You asked for this approval, so the decision is somebody else’s. An author can still approve their own version, which signs it for batches and schedules, but that approval does not count where script_execution.approval_required applies. The Approval card says so.

Two exceptions let you approve your own work so that it counts. Both need a fresh second factor, an authenticator app or a passkey, confirmed in the console. Without one set up, the console says Approving your own script needs a second factor. Set up an authenticator app or a passkey on your account, then try again. Neither is available to AI clients over MCP.

If a security framework that a profile in the workspace declares requires a second person to approve scripts, both exceptions first show a warning that starts A compliance framework this workspace targets and names the framework. Select Approve anyway, or submit the emergency approval with the warning shown, to go ahead. The approval is recorded with the warning.

In a workspace where you are the only account with script:manage, there is nobody to ask. There, Approve on your own version or your own request approves it as the sole editor, after your second factor, and you can turn down your own request. The card then reads Approved by its author as the only person who can edit scripts here, with a second factor.

  • It applies to a client’s own library only. It is not available on the MSP plan or for a script in a library every client shares.
  • The approval counts only while you remain the only editor. When anyone else is given script:manage there, it stops counting, and endpoints that need a second person’s approval stop running the script until someone else approves it.

When you must approve your own version or request and nobody else can approve it in time, select Emergency approval on the Approval card. You need script:approve. The only script editor in a workspace uses Approve instead, as above.

  1. In Reason, say why it cannot wait. The reason is required, up to 1,000 characters.
  2. Optionally, in Ticket, enter the ticket or incident it is for, up to 64 characters.
  3. Select Approve in an emergency, then confirm your second factor.

The approval counts like a second person’s, even where others could have approved. It is never quiet:

  • Outpost raises a warning alert titled Emergency script approval: followed by the script’s name, and emails it to every owner and every person with script:approve except you. Both carry your reason and ticket. For a script in the shared library, the alert and emails go to your practice’s workspace.
  • The audit log records it as script.approve_emergency, with the reason and ticket.
  • The Approval card shows an Emergency approval badge with who approved it, the reason, and the ticket.

A later approval by a second person replaces the emergency one and clears the badge. Editing the script clears it, like any approval.

The profile setting script_execution.require_signed_scripts makes an endpoint refuse every unsigned script, including a draft run on one endpoint and a script typed into an endpoint’s Commands tab. It is off by default. The compliance floors for SOC 2, PCI-DSS, CJIS, NIST 800-53, NIST 800-171, CMMC Level 2, and ISO 27001 turn it on for any scope that declares one of those frameworks. When you run a script on one endpoint, the run form shows whether that endpoint runs signed scripts only, and which profile or floor decided it.

An endpoint that is connected but has not yet received its scripting policy also refuses unsigned scripts. It treats “not told yet” as “signed scripts only”.

These profile settings apply to every script an endpoint runs. See Script execution in the settings reference.

SettingDefaultEffect
script_execution.enabledtrueOff stops the endpoint running any script.
script_execution.max_runtime_seconds3600Longest any script may run before it is stopped.
script_execution.max_concurrent_scripts2How many scripts may run at once on one endpoint.
script_execution.blocked_commandsEmptyCommand names a script may not invoke.
script_execution.run_as_contextsystemThe most privileged account a script may run as.
script_execution.allowed_script_repositoryanyWhere a script must come from: any, library_only (no scripts typed at run time), or client_library_only (this client’s own library, not the shared one). The most restrictive profile wins. A run that breaks it is refused before it is sent, scheduled runs are skipped, and the endpoint refuses it as well.
script_execution.approval_requiredfalseScripts need a second person’s approval. See Second-person approval.
script_execution.log_script_outputtrueOff keeps a run’s exit code and status but not its output. The run shows Output not kept by policy. This applies to one-off and scheduled runs.

The agent receives and enforces its script settings. Changes to profiles, assignments, site membership, and server-role tags reach connected endpoints right away. When script_execution.enabled is off, the agent refuses every script run: one-off, scheduled, library, and AI or MCP requests.

In Profiles > Effective config, script settings show Delivered by Agent (script environment). Agent 0.3.0 or later reports Applied, Pending, or Not reported. See Check delivery.

Interactive terminals have a separate Remote shell setting. Turning off scripts does not turn off interactive terminal access.

CapabilityWindowsLinuxmacOS (Preview)FreeBSD and OpenBSD
Run as SYSTEM (root)YesYesYesYes
Run as Signed-in userYesYes, when the agent runs as root and someone is signed in at the consoleYesNo
Run at sign-inYes, when the agent runs as a serviceYes, with systemd-logindYesNo
Scheduled runs while offlineYesYesYesYes

bash, zsh, and Python run only where they are installed. An endpoint reports which ones it has, and the console leaves out the missing ones.

PermissionAllows
script:readViewing the library, runs, schedules, and custom field definitions
script:manageCreating, editing, duplicating, and deleting scripts, and defining custom fields
script:approveApproving and revoking scripts
script:run_unapprovedRunning a draft on one endpoint, except where script_execution.approval_required applies
script:scheduleCreating, editing, and deleting schedules
command:executeRunning a script and canceling a run

Content is licensed CC BY 4.0. Code samples are MIT. Outpost and the Outpost mark are trademarks of Outpost Business Solutions, PBC and are not covered by either license.