Bring your own policy
Available in Transit 1.0.0 and later. Point Transit at a folder of your own
<vendor>.yamlpolicies (Settings → Policies, or theTRANSIT_USER_POLICIESenvironment variable). See Setting it up for the steps; the sample policies on this page are ready to drop in.
Transit ships a curated, read-only command permit list for each supported vendor. BYOP extends that model to your environment:
- Add allowed commands to a shipped vendor’s list (e.g. a
read-only
showyour platform supports that we don’t list yet). - Cover vendors Transit doesn’t ship — write a policy for any CLI and Transit AI gates commands against it the same way.
- Share with your team — policies are plain local YAML files; the policy directory can point at a shared drive or NAS. Nothing about your policies touches Transit Cloud.
The safety floor doesn’t move
BYOP relaxes nothing that matters:
- Shipped block lists are a hard floor. A user policy can add allowed commands; it can never unblock a command Transit blocks — config-mode entry, write verbs, and shell escapes stay denied even if a user policy tries to allow them.
- The approval click stays. Every command the AI proposes — under any policy — still requires your explicit approval in the app before it runs. Policies are damage control, not the only line of defense.
- A broken policy file fails safe. If your YAML doesn’t parse, the app launches with a warning, ignores the broken layer, and keeps the shipped policy intact.
Your policies, your responsibility
The safety floor and the per-command approval prompt above are guardrails — not a guarantee. A Bring Your Own Policy file is authored and supplied by you (or your team), and it widens what the AI may propose. Any command a user policy permits — and that you approve in the app — runs against your device, and you are solely responsible for the outcome.
- You own what your policies allow. Adding an
allowedpattern, or defining a custom vendor, is your decision. Transit AI does not review, validate, or vouch for user-supplied policies, and is not responsible for any disruption, outage, data loss, configuration change, or other consequence of a command run while a BYOP policy is in effect. - Vet shared and third-party policies before use. A file on a shared drive or NAS can be changed by anyone with write access. Review every policy — including the sample policies below — against your own environment and firmware before pointing Transit at it, and treat a policy directory with the same care as any other code you choose to run.
- Provided “as is.” The sample policies and the BYOP feature are provided without warranty of any kind. This page is product documentation, not a contract — your use of Transit AI remains governed by the Terms of Service.
Setting it up
Three things have to line up: a folder of policy files, Transit pointed
at that folder, and each device’s vendor matching a file. The binding is
the filename — <vendor>.yaml — so getting the name right is the
whole trick.
-
Create a policy folder. Anywhere on your machine (or a shared drive / NAS for team use), e.g.
~/transit-policies/. Put your.yamlfiles directly in it — Transit only reads the top level, so files inside subfolders are ignored. (That’s why the bundled samples live in asamples/subfolder and are never auto-loaded: copy one out into your folder to use it.) -
Name each file after the vendor — the filename is the vendor tag. Use a lower-case, filename-safe name with no spaces:
<vendor>.yaml.- To extend a vendor Transit ships, match its tag exactly so your
allowedpatterns layer on top of the built-in list. The shipped tags arearista_eos,cisco_ios,cisco_ios_xe,junos,linux,nxos, andpan_os— so to add a read-onlyshowto Cisco IOS, your file iscisco_ios.yaml. - To define a vendor Transit doesn’t ship, pick any name and that
name becomes the vendor:
fortios.yamldefines a vendor calledfortios. A custom vendor has no shipped permit list behind it, so every command the AI proposes needs a per-command approval (the “always allow” shortcut is disabled for custom vendors by design).
- To extend a vendor Transit ships, match its tag exactly so your
-
Point Transit at the folder. Either:
- Settings → Policies in the desktop app — paste the folder path and Save (stored in Transit’s config), or
- the
TRANSIT_USER_POLICIESenvironment variable set to the folder path. The environment variable wins: when it’s set, the Settings field shows the path read-only.
-
Relaunch Transit. Policies load at startup, so changes apply on the next launch. Settings → Policies lists the vendors it loaded and shows any warnings — a file that fails to parse is skipped (the shipped policies stay intact), not fatal.
-
Set each device’s vendor to match the filename. When you add or edit a device, choose the vendor whose tag equals your file’s name — for a custom vendor, type that exact name. Transit uses the device’s vendor to decide which policy adjudicates its commands.
The filename is the binding.
fortios.yamlonly governs devices whose vendor isfortios. If the device’s vendor doesn’t match a loaded policy file, your policy silently doesn’t apply — and a custom vendor with no matching policy falls back to default-deny with per-command approval.
Sample policies
Two vetted, read-only starting points for popular platforms Transit doesn’t ship yet. Review every pattern against your environment and firmware version before use — these are conservative baselines, and comments in each file explain why every blocked verb is blocked.
Fortinet FortiOS (FortiGate)
Read-only get/show/diagnose access with reachability checks,
while blocking config mode, the execute outage/restore verbs, the
execute backup exfiltration channel, lateral movement via
execute ssh/telnet, and the execute shell escape. FortiOS
accepts prefix abbreviations (conf = config), so the policy’s
alias map expands the common contractions before matching — an
abbreviated verb can’t sneak past the block list.
mode: gated
precedence: block-wins
canonicalization:
aliases:
conf: config
exec: execute
diag: diagnose
sh: show
g: get
allowed:
- "^get( |$)"
- "^show( |$)"
- "^diagnose sys status"
- "^diagnose sys top( |$)"
- "^diagnose sys session list"
- "^diagnose hardware "
- "^diagnose ip arp list"
- "^diagnose ip route "
- "^diagnose vpn tunnel list"
- "^diagnose firewall statistic show"
- "^execute ping( |$)"
- "^execute ping6( |$)"
- "^execute traceroute( |$)"
- "^execute log filter "
- "^execute log display( |$)"
blocked:
- "^config( |$)"
- "^execute shell"
- "^execute ssh( |$)"
- "^execute telnet( |$)"
- "^execute reboot"
- "^execute shutdown"
- "^execute factoryreset"
- "^execute restore"
- "^execute erase"
- "^execute formatlogdisk"
- "^execute set-next-reboot"
- "^execute batch"
- "^execute cfg"
- "^execute backup"
- "^execute usb"
- "^execute update-now"
- "^execute date"
- "^execute time"
- "^execute disconnect-admin-session"
- "^execute log delete"
- "^execute log roll"
- "^diagnose sys kill"
- "^diagnose sys session clear"
- "^diagnose ip arp delete"
pipe_allowed:
- "^grep( |$)"
pipe_blocked: []
MikroTik RouterOS v7
RouterOS commands are slash-paths with a trailing verb
(/ip address print reads; /ip address add writes). The policy
allows paths ending in read verbs (print, screen-only export,
traffic monitors) plus reachability tools, and blocks the mutation
verbs after any path, the /system outage and code-execution trees,
/tool fetch (file ingress), and file= anywhere — print file= and
export file= write to flash storage.
mode: gated
precedence: block-wins
canonicalization:
aliases: {}
allowed:
- "^/[a-z][a-z0-9 /-]* print( |$)"
- "^/[a-z][a-z0-9 /-]* export( |$)"
- "^/export( |$)"
- "^/interface monitor-traffic "
- "^/tool monitor-traffic "
- "^/ping( |$)"
- "^/tool ping( |$)"
- "^/tool traceroute( |$)"
blocked:
- " (add|set|remove|edit|move|enable|disable|unset|comment)( |$)"
- "^/system (reboot|shutdown|reset-configuration|backup|package|upgrade|routerboard|license)"
- "^/system script"
- "^/system scheduler"
- "^/import"
- "^/execute"
- "^/console"
- "^/tool (fetch|bandwidth-test|traffic-generator|e-mail|sms)"
- "^/file"
- "^/password"
- "file="
pipe_allowed: []
pipe_blocked: []
Policy file anatomy
| Field | What it does |
|---|---|
mode | gated runs the permit list; unrestricted skips it (every command still needs your click — used for generic Linux). |
precedence | Tiebreak when a command matches both lists. block-wins is the safe default. |
canonicalization.aliases | First-word contractions the CLI accepts (wr → write). Without these, an abbreviation can sneak past the block list. |
allowed / blocked | Anchored regex patterns matched against the (lower-cased, alias-expanded) command. No match at all = denied. |
pipe_allowed / pipe_blocked | Same idea, applied to every stage after a |. An empty pipe_allowed refuses piped commands entirely. |
The default is always deny: a command that matches nothing is refused, so an incomplete policy fails toward safety.