Before a script can run, BaudBound calculates what the script needs and shows that information for review.
Permissions describe operations that matter to the person approving the script. Examples include reading a file, controlling the keyboard, or starting a process.
Capabilities are internal feature categories used to confirm that package declarations match the executable graph. Users do not add or approve capabilities separately.
Risk shows how carefully the package should be reviewed. It is calculated from the highest risk operation in the package.
Approval records that the current package revision and its calculated access were accepted. A changed package needs a new approval. Approval never disables validation or platform checks.
| Level | Meaning | Examples |
|---|---|---|
| Low | Local workflow behavior with limited external impact | logging, delay, calculation, text transformation |
| Medium | Reads, controlled writes, communication, or visible desktop effects | file read/copy, HTTP request, clipboard, notification, serial write |
| High | Broad mutation, input control, persistent or global data, secrets, listeners | keyboard/mouse, file write, webhook bind, secret read |
| Dangerous | Arbitrary process or command behavior and irreversible operations requiring focused review | run process, shell command, file deletion |
Risk is a review priority, not a verdict. A low-risk workflow can still disclose data through careless logging, and a high-risk workflow can be legitimate when its scope is understood.
The runner derives permissions from executable action types and variable scopes. It rejects missing declarations, unused declarations, duplicates, or a declared risk lower or higher than the calculated value.
| Permission | Risk | Behavior that requires it |
|---|---|---|
beep |
Low | Generate a system beep |
calculate |
Low | Evaluate supported arithmetic |
delay |
Low | Pause execution |
log |
Low | Write a runner log entry |
set_local_variable |
Low | Write run-scoped data |
text_transform |
Low | Transform text or structured text input |
webhook_response |
Low | Complete the current waiting webhook |
download_file |
Medium | Download network content to a file |
file_copy |
Medium | Copy a file |
file_move |
Medium | Move or rename a file |
file_read |
Medium | Read file contents |
http_request |
Medium | Send an outbound HTTP request |
open_application |
Medium | Open an application through a native adapter |
play_sound |
Medium | Play package or filesystem audio |
process_query |
Medium | Inspect process state |
read_clipboard |
Medium | Read text from the native clipboard |
screen_pixel_read |
Medium | Read a screen pixel on supported desktops |
serial_write |
Medium | Send data to a configured serial device |
set_persistent_variable |
Medium | Store script data between runs |
show_message_box |
Medium | Display an interactive desktop dialog |
show_notification |
Medium | Display a desktop notification |
websocket_write |
Medium | Write to a connection associated with a WebSocket run |
window_query |
Medium | Read active-window information |
write_clipboard |
Medium | Replace native clipboard content |
file_write_limited |
High | Create, overwrite, or append file content |
keyboard_control |
High | Send native keys or text |
mouse_control |
High | Move or click the native pointer |
process_kill |
High | Terminate a matching process |
read_secret |
High | Resolve runner-supplied secret declarations |
serial_input |
High | Read unattended input from a serial mapping |
set_global_variable |
High | Change runner-global data |
startup_trigger |
High | Start a script automatically when its service loads |
sub_script_run |
High | Execute another installed and approved script |
webhook_public_bind |
High | Register an inbound HTTP route |
websocket_public_bind |
High | Register an inbound WebSocket route |
window_focus |
High | Change foreground-window focus |
delete_file |
Dangerous | Permanently remove a file |
read_sensitive_file |
Dangerous | Read from an absolute, sensitive, or runtime-selected filesystem path |
run_process |
Dangerous | Start an executable with arguments, wait for completion, and capture its exit status and output |
run_shell_command |
Dangerous | Execute a command through a shell interpreter |
write_any_file |
Dangerous | Write to an absolute, sensitive, or runtime-selected filesystem path |
Trigger nodes such as Manual, Schedule, File Watch, Hotkey, and Process Started can be permissionless while still declaring machine-checkable capabilities and requiring service prerequisites.
File permissions depend on the configured path. A bounded relative path uses file_read or file_write_limited. It resolves inside workspaces/SCRIPT_ID under the runner home, giving each installed script its own limited workspace. Parent traversal and symbolic-link components that escape this directory are rejected.
An absolute path, a sensitive system location, a path containing runtime variables, or another path whose location cannot be proved in advance requires read_sensitive_file or write_any_file. The same rule applies to read, write, append, copy, move, delete, download destinations, and File Watch. This makes arbitrary filesystem access visible during approval instead of treating every file action as equally broad.
Capabilities describe runtime subsystems, not user consent by themselves. Current categories are:
| Family | Capabilities |
|---|---|
| Action and data | action.calculate, action.delay, action.log, action.text, runtime.variables, runtime.persistent_storage, runtime.secrets |
| Files and network clients | action.file, action.http |
| Processes and scripts | action.process, action.sub_script |
| Desktop | action.clipboard, action.keyboard, action.message_box, action.mouse, action.notification, action.pixel, action.sound, action.window |
| Serial | action.serial, trigger.serial_input |
| Network replies/listeners | action.webhook_response, action.websocket, trigger.webhook, trigger.websocket |
| Control flow | runtime.break_loop, runtime.color_match, runtime.continue_loop, runtime.for_each, runtime.if, runtime.repeat, runtime.switch, runtime.while |
| Other triggers | trigger.file_watch, trigger.hotkey, trigger.manual, trigger.process_started, trigger.schedule, trigger.startup |
The editor node registry generates the node-to-capability contract embedded in the Rust security crate. During import, the runner recalculates required capabilities from program.json and compares them with package declarations. A package cannot gain access by declaring an unrelated capability, and it cannot omit one required by its program.
Approval records:
An approval is current only while the installed package hash and permission set match. Updating package content invalidates the previous approval. An unchanged display name does not preserve trust.
Revocation removes consent for the current revision without removing the package. The runner removes its active trigger registrations and rejects new manual, automatic, queued, and sub-script execution attempts until that revision is approved again.
Disabling a script is separate from revoking approval. A disabled script remains approved and installed, but the runner removes its active trigger registrations and rejects every new execution attempt. A run that was already executing is not forcefully cancelled.
The approval button remains blocked when validation, integrity, target, or policy checks make approval unsafe.
Replace SCRIPT with the installed name or ID:
baudbound script inspect SCRIPT
baudbound script approval SCRIPT
baudbound secret list SCRIPT
baudbound script approve SCRIPT
To revoke approval:
baudbound script revoke-approval SCRIPT
Use --json on supported inspection commands for automation. Do not parse decorative table spacing.
The operator controls three independent switches under [security.policy]:
| Setting | What false blocks |
|---|---|
allow_shell_commands |
Every run_shell_command action |
allow_dangerous_permissions |
Every package that requires a Dangerous permission |
allow_public_network_listeners |
Webhook and WebSocket triggers that bind beyond loopback |
Shell commands must pass both the shell-specific setting and the Dangerous-permission setting. A current approval does not bypass these checks. Policy is applied during inspection, import, approval, trigger registration, and execution. A blocked script reports the exact setting involved.
The defaults are true so an update does not silently disable packages that a user already reviewed. Set a switch to false when the machine does not need that behavior. Policy is defense in depth. It must not be used to make package declarations inaccurate, and a package or repository cannot change it.
Continue with Security Model, Secrets, and Network Access.