TransIT AI

Bring your own policy

Available in Transit 1.0.0 and later. Point Transit at a folder of your own <vendor>.yaml policies (Settings → Policies, or the TRANSIT_USER_POLICIES environment 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 show your 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 allowed pattern, 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.

  1. Create a policy folder. Anywhere on your machine (or a shared drive / NAS for team use), e.g. ~/transit-policies/. Put your .yaml files directly in it — Transit only reads the top level, so files inside subfolders are ignored. (That’s why the bundled samples live in a samples/ subfolder and are never auto-loaded: copy one out into your folder to use it.)

  2. 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 allowed patterns layer on top of the built-in list. The shipped tags are arista_eos, cisco_ios, cisco_ios_xe, junos, linux, nxos, and pan_os — so to add a read-only show to Cisco IOS, your file is cisco_ios.yaml.
    • To define a vendor Transit doesn’t ship, pick any name and that name becomes the vendor: fortios.yaml defines a vendor called fortios. 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).
  3. 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_POLICIES environment variable set to the folder path. The environment variable wins: when it’s set, the Settings field shows the path read-only.
  4. 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.

  5. 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.yaml only governs devices whose vendor is fortios. 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

FieldWhat it does
modegated runs the permit list; unrestricted skips it (every command still needs your click — used for generic Linux).
precedenceTiebreak when a command matches both lists. block-wins is the safe default.
canonicalization.aliasesFirst-word contractions the CLI accepts (wrwrite). Without these, an abbreviation can sneak past the block list.
allowed / blockedAnchored regex patterns matched against the (lower-cased, alias-expanded) command. No match at all = denied.
pipe_allowed / pipe_blockedSame 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.