Kotoba

Where to start

What Kotoba isWho she is and where she runs, in one page
InstallingOne package, two commands
First runA key, a model, her first words
The approval gateHow she asks before she acts
The two voice modesLocal voice, or the agent tunnel
The soul fileChange who she is
RoadmapWhat grows next, and what was cut on purpose

Or a section

↑↓ move openesc close124 pages
All pages

Security3 of 10

Dangerous commands

About 4 minutes to read

On this page

A command that matches one of fourteen patterns is labelled dangerous. Nothing about it is automatic: it never auto-runs, no saved grant of either kind covers it, and neither "always allow" key appears on its card. It asks every time.

Say plainly what this is: a denylist of fourteen regular expressions read over the text of the command line. It is not a capability model and it is not a simulation of what the command would do. It catches the shapes it names.

The fourteen labels

Read out of core/approval.py. The label is what the card says the command is.

LabelThe shape it matches
recursive-deleterm with any recursive flag, rd/rmdir /s, Remove-Item -Recurse
delete-root-or-homea delete whose last argument is /, ~, /*, $HOME, a drive root or %USERPROFILE%
privilege-escalationsudo, su, doas, Start-Process -Verb RunAs
pipe-to-shella download piped into a shell or into Invoke-Expression
raw-disk-writedd … of=, or a redirect into a raw disk device
filesystem-formatmkfs, fdisk, mke2fs, format <drive>, diskpart, bcdedit, Format-Volume
fork-bombthe classic self-referencing function
recursive-chmod-rootchmod -R applied to / or ~
power-controlshutdown, reboot, halt, poweroff, init 0, Stop-Computer, Restart-Computer
history-or-key-wipea redirect that truncates shell history, ~/.ssh/ or ~/.aws/
destructive-findfind with -delete, -exec or -execdir
file-truncate-shredshred, truncate, or tee redirected to an absolute path
registry-deletereg delete, Remove-ItemProperty
backup-wipevssadmin/wbadmin delete, cipher /w

Four of them exist only for Windows, where the same harm wears different names and the card could not otherwise say what the command was.

recursive-delete asks only for a recursive flag, in any spelling or bundle. Requiring -f as well would read a recursive delete of a home directory as ordinary, because -f only silences prompts while -r is the flag that empties the tree.

destructive-find is on the list because find is one of the 29 auto-safe read commands. Without it, a bare find . -delete would have run in the working folder with no card.

What is refused outright, and what merely asks

Nothing on this list is refused outright when there is someone to ask. The label changes what the card says and removes both "always allow" keys. You can still approve it, and it will run.

The one case where a dangerous label becomes a refusal is when no approval channel exists — a sessionless or scripted call with no gate wired. There, shell refuses a labelled command rather than running it unattended, and answers in plain language rather than with an error.

Under KOTOBA_SANDBOX=docker, where ordinary commands run without a card, a dangerous label is still stopped and still asked. Measured: with the docker backend selected, rm notes.txt and npm install run unasked, while sudo apt update, shutdown now, a download piped into a shell, and a redirect to a raw disk device all raise a card.

What a denylist over shell text implies

Three things, and they are worth stating rather than leaving to inference.

It matches text, not behaviour. A command that reaches the same outcome by a spelling the list does not name is not labelled. The list is not a claim to have enumerated destruction.

The label is not the safety. What makes the default setting defensible is not this list — it is that on KOTOBA_SANDBOX=local, everything that is not a plain read inside the working folder asks anyway, unless you saved a grant for it. The dangerous list adds two things on top: it removes the ability to save a grant at all, and it gives the card an honest word for what it is looking at.

It is the last line under docker, and it is a thin one. With the docker backend, ordinary commands run without a card and the container is the boundary. If you are relying on this list to catch things there, you are relying on a denylist over text. The container is what is actually protecting you.

Where it sits relative to the rest

command
   ├── matches a dangerous pattern?  → always a card, no grant can be saved
   ├── on the allow-list?            → runs (empty in the running system)
   ├── covered by a saved grant?     → runs
   ├── a plain read inside the jail? → runs
   └── otherwise                     → a card

The Python path has its own list of seven patterns, over source rather than shell text. It works the same way and has the same limits: see execute_code.