# Security (/en/docs/b24/security)

What WireCat CLIs share — the keyring, permissions, MCP and what never reaches a log — is on the
[shared security page](/llms.mdx/docs/security/content.md). This page keeps only what is particular to `b24`.

`b24` keeps its settings in `config.json` and its state in the folders `b24 doctor` shows. It talks only to the
portal of the profile's webhook or local application, and to `oauth.bitrix.info` for an application's tokens, over
HTTPS, and never follows a redirect.

The webhook's address carries its secret in its path, so the whole address is the password. `b24` keeps it in the
system keyring (service `bitrix24-cli`, account `token:<profile>`), or in a private file with
`--credential-storage file`, and never writes it to the output, an error, a log or a run record: a run keeps the
method and `/rest/:user/:token/<method>`, never the address. An error keeps Bitrix24's error code and the names of
the fields it refused, never Bitrix24's description, which can quote what was typed.

A local application's sign-in is kept in the same place (account `oauth:bitrix24:<profile>`): the application's
code and key, the access token, which lasts an hour, and the refresh token, which lasts 180 days and changes at each
renewal. The key goes only to `oauth.bitrix.info`, as Bitrix24 asks, never to the portal; the token goes to the
portal in the body of each call, never in its address. None of them reaches the output, an error, a log or a run
record. The sign-in returns through the page `https://wirecat.dev/webhooks/apps/b24-callback`, which passes the one-time
code to `b24` on this computer in your browser; the code works for 30 seconds and only with the key. Bitrix24 has no
call that revokes a token: `session end` forgets the sign-in here, and deleting the application in the portal stops it.

The webhook acts with the rights of the employee who made it. A webhook made by an admin lets an agent read and
change everything in the CRM. `session status --check` says whose rights it carries; make the webhook with an
employee whose rights fit the work, and only the scopes it needs. `sync` uses `crm`, `user_basic` for employees'
e-mail addresses and `department` for the company structure. `user_basic` is enough: `sync` never changes an
employee, and the full `user` scope adds the right to invite and edit them. The sync stores each employee's name,
e-mail address, position and department head in the local store, where every WireCat tool can read them.

Unless the webhook's user is a Bitrix24 administrator, the sync copies only their own clients: the contacts and
companies assigned to them or named on their deals and leads. Lists show phones and e-mails of those alone; `people
show` and `organizations show` give them for anyone else's, at most 100 a day for the user and their agents together.
That count is kept on this computer, so it stops an accident or an agent, not someone who means to take the base:
Bitrix24's own access rights do that.

Every write is checked against the permissions and kept in the send journal. `B24_READ_ONLY=1` refuses every write.
Assigning a record to another employee is refused until you allow it. A stage change can still start the portal's own
robots, which may write to your clients: if your portal has such robots, set `permissions.deals.move` and
`permissions.leads.move` to `readonly` or `deny` before an agent gets the profile over MCP, where `ask` does not ask
([permissions](/llms.mdx/docs/b24/permissions/content.md#stage-changes-start-the-portals-robots)). Every write that sets a stage checks them; a won or lost stage, and `close`, check
`deals.close` or `leads.close` too, and `api call` with a `stageId` checks both. A deal or lead `--field` that names a
stage, a pipeline or an owner is refused. Deleting a deal or a lead asks first. `api.crm.deal.update: deny` also stops
`deals update`, `move` and `close`, and at `ask` they ask too.

`search all` reads what the list keys allow: under `deals.list: deny` it leaves deals out, under `leads.list: deny`
leads, and names each kind it left out in `missing` and on stderr. With every kind it was asked for denied, it is
refused.

`api call` works from an allow list. It allows the CRM, catalog, user and department reads `b24` makes itself, and the deal, lead,
contact and company writes. Contact and company reads are an administrator's alone, whatever the permissions say. Reads and writes both check the key of the command that reads or writes the same records:
`api call crm.deal.list` checks `deals.list`, and `crm.item.update` with `entityTypeId` 2 checks `deals.update`.
`department.get` checks `users.list`, and `crm.mycompany.*` checks `organizations.list`. A body
that names one field twice in any spelling (`assignedById` and `ASSIGNED_BY_ID`, `fields` and `FIELDS`), an
`entityTypeId` that is not a plain number, and a method with a suffix other than one `.json` are refused before
anything is sent. A delete asks. Every other method asks too, and is refused without a terminal unless you pass
`--yes`. Methods that message people, publish or send data out are refused until you allow them: `im`,
`imopenlines`, `imbot`, `imconnector`, `log.blogpost`, SMS, mail, telephony, workflows, CRM activities, tasks,
`user.add`, public file links, `event.bind` and `batch`. Their reads are refused too, since they hold messages,
e-mails and tasks. `api show <method>` names a method's level. `api call` is
not offered over MCP.

`schedule command` installs a timer (systemd, launchd or Task Scheduler) that runs `b24` on its own, with no
terminal. The timer runs `b24 schedule exec <file>`, and the schedule file in the state folder holds the words, the
profile, your `PATH` and the folders `b24` uses (`B24_CONFIG_DIR`, `B24_STATE_DIR`, `MESSAGING_STORE`), never the
webhook's address. Each run checks the permissions again. `B24_READ_ONLY` refuses
`schedule command`, `remove`, `run` and `exec`, and no MCP tool offers `schedule`.

A write that got no answer is not sent again: it is `outcome_unknown` with its `operation_id`. Check the portal, and
write it again only if it is not there: Bitrix24 would make a repeat a second time.

`b24 work mcp serve --http` listens on `127.0.0.1` only, for browser apps that reach it through your own
tunnel. Each app logs in with a one-time code, and the server keeps a hash of each login it gives, in the state
folder, readable by you only. `b24 work mcp revoke` forgets every one of them.

A run record keeps the command line as you typed it, so `b24 runs show` tells you what was run. A secret is still
stored as `[redacted]`: an option named like a token or password, a password in a link, a long opaque string. A
phone number is replaced by `[redacted]` inside the word you typed, message text included: one written with its "+" and
country code, or 11 to 15 digits in a row, so a long id of that length is hidden as well. To keep none of the words
you type, run `b24 work config set record_input false`.

A secret is also found by what it looks like, in a run record and in a kept error message: a token in a known
format (GitHub, OpenAI, Slack, AWS, Stripe, npm and the like), a `Bearer` credential, a random-looking string of 20 or
more characters, and a random-looking run of 20 or more lower-case hex characters, such as a hex key or a full commit
hash. The value after a secret name is hidden too, whether it follows `=`, `:` or a space: `password=`, `API_TOKEN=`,
`password hunter2`, `pin 1234`. Some secrets look like ordinary words and stay: a value of letters only after a
secret name and a space (`pin this message` stays), a hex key in upper case, a short commit hash or a UUID, a short
password typed without a secret name before it, and a secret inside a link or a file path unless it is in a known
format or after a secret name.

`config.json` is saved readable by you only (`0600`), and its folder is created for you only (`0700`). A file or
folder made by an older version may be open to other users of the computer: `b24 doctor` lists each under
`files.problems` and prints the `chmod` that fixes it. Windows is not checked. Report a vulnerability as [SECURITY.md](https://github.com/WireCatLabs/bitrix24-cli/blob/main/SECURITY.md)
says.
