skip to content

Keeping Secrets Out

Marking a value as a secret so the tooling tracks it apart from ordinary variables, and holding one in a store a script cannot read while the request still gets the real thing.

part ofAPI & DB clientsoverview, primer and where to startread it →
on this pageshow

explore

questions

4

In a Postman variable, how is a value marked as secret, and does the collection format's schema declare it?

level: middleimportance: must knowfreq 45%

answer

  1. Ask which authority owns the field
  2. The SDK and the document schema disagree
  3. A flag beside the value, not a type
  4. One array in the scope has one entry
  5. The enum has four values; check them

basics

~20 s

Postman's collection SDK marks a secret with a Boolean secret property on a Variable, and it is the variable scope's only tracked property. The collection format's schema never declares it, and there is no variable type called secret.

solid answer

~40 s

The **collection SDK** models it as a Boolean: `secret: true` sits on a `Variable` beside `system` and `disabled`. It is set from a definition object, or through `VariableScope.set(key, value, options)`, whose third argument is overloaded — a string is read as a type, an object is read as `{ type, secret }`. `secret` is also the sole entry of the SDK's `TRACKED_PROPERTIES`, so with mutation tracking on the flag is recorded with the write and replayed with it. The **collection format** is a different authority: its `variable` definition declares `id`, `key`, `value`, `type`, `name`, `description`, `system` and `disabled`, with `type` an enum of `string`, `boolean`, `any` and `number`. `secret` is not among them, and there is no `"secret"` type — the one `"type": "secret"` in the SDK sits inside a JSDoc example comment.

code

javascript · 2 lines
javascript
pm.environment.set('apiKey', 'a1b2c3', { secret: true });
pm.collectionVariables.set('tenant', 'acme', 'string');

go deeper

for a junior

Recall that marking a value secret in Postman is a true/false flag on the variable, not a value you put in its type field. Know the four types the format allows.

for a middle

Be ready to explain the overloaded third argument of a variable scope's set, and why the same flag survives a tracked write when nothing else about the variable does.

for a senior

Show you separate authorities: the document schema declares one set of properties, the SDK's Variable carries another. Say which one owns the flag before you say what the flag does.

for a principal

Own the consequence of a marking that lives outside the document format: what portability guarantees you actually have when a collection moves between tools, and where you would put the boundary instead.

## The marking is a Boolean, not a type In Postman's **collection SDK** a variable is an object built around a `key` and a `value`, with a small set of flags beside them. One of those flags is **`secret`**. The SDK declares it on `Variable.definition` as an optional Boolean — "indicates whether this variable contains secret/sensitive data" — and applies it in `Variable.update` with a plain assignment guarded by a presence check, exactly the way it applies `system` and `disabled`. So "this value is a secret" is a **true/false property sitting next to the value**. It is not a value of `type`, and there is no separate secret-variable class anywhere in the SDK. That distinction is the whole question. `type` and `secret` answer different things: `type` says how the value is coerced when it is read back; `secret` says the value is sensitive. Conflating them produces a variable that either fails to coerce or fails to be marked. ## Where the flag gets set There are two entry points, and both go through the same code: - **From a definition object.** When a scope is constructed from JSON, each entry's `secret` key — if it is present — becomes the Boolean on the `Variable`. - **From `VariableScope.set(key, value, options)`.** The third parameter is deliberately overloaded: pass a **string** and the SDK reads it as a type; pass an **object** and it reads `{ type, secret }` off it, taking `secret` only when it is a genuine Boolean. The sandbox's `pm.environment`, `pm.collectionVariables` and `pm.globals` are `VariableScope` instances themselves, so a script marks a value with that same third argument rather than with any special API of its own. ## `secret` is the scope's only tracked property `VariableScope` declares a constant array named `TRACKED_PROPERTIES` whose **single entry is `'secret'`**, described in the source as the list of "properties that should be tracked in mutations when set on variables". When mutation tracking is enabled, `set` records the write and picks `TRACKED_PROPERTIES` out of the options object into that record. The consequence is concrete: a value a script marks secret is **still marked** when the recorded write is replayed onto a scope elsewhere. Nothing else about a variable — not its type, not its description, not its `system` flag — is preserved that way. If you ever need to argue that the flag is a first-class part of a variable rather than a cosmetic hint, this one-entry array is the evidence. ## What the collection format declares — and does not The **collection format** is a different authority from the SDK, and this is where candidates go wrong. The format's `variable` definition declares these properties, and `type` is restricted to a four-value enum: | property | declared by the collection format | present on the SDK's `Variable` | |---|---|---| | `id`, `key`, `value` | yes | `key` and `value` | | `type` | yes — `string`, `boolean`, `any`, `number` | yes | | `name`, `description` | yes | `description` | | `system` | yes, Boolean | yes, Boolean | | `disabled` | yes, Boolean | yes, Boolean | | **`secret`** | **not declared** | **yes, Boolean** | So the honest sentence is: *the flag is an SDK and runtime notion, and the document schema never names it.* Say "the collection file declares `disabled`" and "the SDK's `Variable` carries `secret`"; do not blur the two into "Postman lets you". ## Why the secret-type myth survives The SDK's `variable.js` carries a JSDoc `@example` block above the definition typedef, and that example shows an object containing `"type": "secret"`. It is a **comment**, and a comment is documentation rather than source. There is no such type: the enum does not admit that value, and the string appears nowhere in the schema definitions at all. Reading an example block as if it were a schema is how a plausible-sounding, entirely wrong answer gets repeated in interviews. The check that settles it takes seconds: look at the enum. ## What the flag buys, and what it does not - It does **not** encrypt the value, in the file or in memory. - It does **not**, on its own, stop a script from reading the value — blanking a value for scripts is a separate runtime step driven by what the host answers when the runtime asks about that secret. - It does **not** appear as a declared field of the collection document. - It **does** mark the value so the surrounding machinery can treat it differently from an ordinary variable, and it **does** survive a tracked write, which is more than any other property manages. Answer the question in that order — Boolean flag, set through the overloaded third argument, the scope's one tracked property, absent from the format's schema — and the "secret type" trap never gets a chance to fire.

  • Why does the SDK's variable scope track that one property and nothing else?
    Because a recorded write has to be replayable without losing the fact that the value is sensitive. The scope's tracked-properties array holds a single name, `secret`, and `set` picks it out of the options object into the recorded mutation. Type, description and the system flag are not carried, so a replayed write restores the value and its sensitivity, nothing more.
  • A colleague shows you a collection whose variable has "type": "secret". What do you tell them?
    That the format's `type` enum admits only `string`, `boolean`, `any` and `number`, so nothing reads that value as a type. The string appears once in the SDK, inside a JSDoc example comment, which is documentation rather than schema. The real marking is the Boolean `secret` property on the variable, and their file is not marking anything.

saying these in an interview costs you the question

  • Says a variable's type is set to secret
  • Claims the collection schema declares a secret property
  • Thinks the flag encrypts the value in the file
  • Reads a JSDoc example block as the schema
  • Assumes the flag alone hides the value from scripts
open as a page

In a Postman script, what does pm.vault.get('apiKey') return, and how must the script consume it?

level: juniorimportance: should knowfreq 34%

basics

~20 s

It returns a Promise, so a Postman script must await it or chain then; the value never arrives synchronously. The vault interface offers get, set and unset, all promise-returning, unlike a variable scope's synchronous get.

open as a page

In a Postman run, why can a script read an environment variable as undefined while the request still sends its value?

level: seniorimportance: should knowfreq 26%

basics

~20 s

Postman's runtime clones the environment, globals and collection scopes for a script and blanks any flagged secret the host declined to expose, while the request keeps substituting from the untouched originals. Script and request are deliberately given different views.

open as a page

In a Postman run, why might a vault secret resolve into one request's URL but not into another's?

level: seniorimportance: nice to knowfreq 17%

basics

~20 s

A vault variable can carry a domains array of URL match patterns. The runtime compiles them and offers the variable only to requests whose URL they match, so a non-matching URL keeps the token literal.

open as a page