---
title: "Secrets"
description: "How an agent uses a password or a token without ever reading it: what the daemon catches, what it replaces, where a value may be typed, and how to reach one from a command line."
canonical: "https://scalebrowser.net/docs/secrets"
last_modified: "2026-09-20T14:10:27.000Z"
---

> ## Documentation Index
> Fetch the complete documentation index at: https://scalebrowser.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Secrets

> How an agent uses a password or a token without ever reading it: what the daemon catches, what it replaces, where a value may be typed, and how to reach one from a command line.


An agent that signs into a site holds a password. An agent that creates an API key sees it on the page. In both cases the value ends up in a transcript that leaves your machine, and there is no way to take it back.

The secret layer closes that. Values still get used; they stop being readable.

## What an agent gets instead of a value

A placeholder:

```text
{{sb:9f3c1a:npmjs.com/token}}
```

The agent can pass it wherever a value would go. When it does, the daemon looks the value up, checks where it is going, and types the real thing. The agent never learns it.

The first time a value shows up, the reply also carries a short profile of it: what kind of value it is, where it may be used, how it stands, and when it expires. Later mentions are the placeholder alone.

```json
{
  "secrets": [{
    "secret_ref": "{{sb:9f3c1a:npmjs.com/token}}",
    "kind": "api_token",
    "detected_by": "format:npm",
    "usable_on": ["npmjs.com"],
    "state": "quarantined"
  }]
}
```

The middle part changes every time the daemon restarts. A placeholder from before a restart stops working, and the agent gets a clear message saying so, plus the tool that hands out the current one (`secret_list`). That tool never answers with a value either.

## What gets caught

Four things, in this order, and the first one that fits wins.

**A value the daemon already knows.** Anything in your vault: a stored password, a two-factor key, a value caught earlier. Found wherever it turns up, including base64, percent-encoded, inside a URL, split across three elements of a page, or as a fragment of at least sixteen characters. This is the strong case, and it is strong because the daemon is the SOURCE of the value rather than a guesser about it.

**A provider format with a checksum.** npm and GitHub tokens carry a checksum in their last six characters. If it does not add up, the value is treated as **not recognised** rather than as a token, because the alternative would censor every example in every documentation page.

**A provider format without one.** AWS, Stripe, Slack, Google, GitLab, SendGrid.

**What the page itself says.** A copy button beside a random-looking string, a warning that you will not see it again, a read-only field holding something random. That is how every service shows a freshly created key.

Anything else that looks random is **censored and reported**, not decided silently. You see it in the profile's key list marked uncertain, and one click releases it if it was harmless. A release lasts: the same value is not flagged again.

Confirmation codes from a mailbox are the deliberate exception. They stay readable while the agent works, because they are worthless in ten minutes and because hunting six-digit numbers would hit prices, order numbers and clock times. They are only ever described, never quoted, in anything that gets written down.

## Where a value may be typed

Every value carries a binding, and the check is made against the frame that is actually being written into, never against an address the agent names. A page that looks like your bank but lives somewhere else gets nothing.

| Setting | What it means |
|---|---|
| Its site, matching fields | The default. Only on the value's own site, over https, and only into a field that matches. |
| Its site, any field | Same site, any field you point it at. |
| One exact host | For a service with several hostnames, when only one should get it. |
| Anywhere | No check. The value can then be typed on any page the agent reaches. |

If a use is refused, the agent is told which check refused and what to do instead. **Nothing is typed**, not one character.

Two places take no placeholder at all, on purpose. The clipboard knows text and no destination, and the paste is a separate step, so nothing could check where the value lands. `interact` uploads files and picks options; it types no form text.

## What is filtered

Everything an agent reads: the reply of every tool, the page map, the text of a page, the error message of a failed call, the activity trail your dashboard shows, and the events it streams. A screenshot has the value painted over.

If the daemon cannot run the check for some reason, the reply is **held back** rather than sent unchecked. Three calls still answer: releasing a profile, renewing a reservation, stopping a browser. They carry nothing from the page, and blocking them would strand the agent with a browser it cannot close.

A PDF and a downloaded file are handled differently: they are read, and if a stored value is in them, the file is not handed over at all. Painting a rectangle would not help, because a value in a PDF is selectable text rather than pixels.

## Using a value outside the browser

Sometimes the point of a token is a command, not a form. The daemon runs it for you:

```bash
scalebrowser-daemon run --profile <id> --env NPM_TOKEN=npmjs.com/token -- npm publish
```

The daemon starts the command with that one value in its environment and gives you the output back, filtered. The value never crosses a socket and there is no endpoint that hands it out.

Two things to expect. **At least one `--env` is required**: without the rule a publish would carry every value that profile holds. And the command runs **without a terminal**, so progress bars and colours look different than usual. That is what makes the output searchable, because a stray control character in the middle of a value would let a screen show it while a search misses it.

## Switching it off

Settings → Secret layer. It is on from the moment you install, and it stays on unless you turn it off.

With it off, nothing is caught and nothing is replaced: a token a page shows lands in the agent's context in full, and a stored password can be typed on any site the agent reaches. Values already stored stay stored and stay unreadable.

## What it does not do

- **It does not read your files.** A `.env` on your disk that never went through Scalebrowser is not its business.
- **It does not touch network traffic.** No interception, no broken connections.
- **It does not work backwards.** Runs from before it was switched on are untouched.
- **It does not ask permission per use.** A prompt on a second device would end the unattended run this product exists for; the destination check does that job instead.
- **It does not filter the direct CDP path or the AdsPower adapter.** Those are read by your own code, which a placeholder would break. There is a call for filtering text yourself: `POST /v1/profiles/:id/secrets/scrub`.
- **It does not stop an agent that is trying.** Anything an agent may use, it may also write down somewhere. What the layer removes is the need to see a value in order to use one. Every secret manager has this same edge.
