Shipfox
Reference

Secrets and Variables Reference

Store secrets (write-only, encrypted) and variables (readable config) in your Shipfox workspace, and use them in workflows with ${{ secrets.KEY }} and ${{ vars.KEY }}.

Shipfox stores two kinds of workspace configuration for workflows. A variable is plain configuration (an environment name, a URL, a flag) that workflows read with ${{ vars.KEY }}. A secret is a sensitive value (an API token, a password) that workflows bind with ${{ secrets.KEY }}. It is write-only after creation and never resolves outside the runner.

Managing them

Both live in workspace settings (Settings → Secrets and Settings → Variables).

  • Keys match ^[A-Z_][A-Z0-9_]*$ (uppercase, digits, underscores).
  • Variables are readable: the settings page shows values, and you can edit them in place.
  • Secrets are write-only: after you save one, no screen or API returns the value. You can only overwrite or delete it. Secrets are encrypted at rest with per-workspace keys.
  • Scopes. Values are workspace-scoped. A project-scoped value with the same key overrides the workspace one (project-scoped management is API-only today).
  • One workspace cap counts secrets and variables together. Self-hosted deployments set it with SECRETS_MAX_PER_WORKSPACE.

Using variables

${{ vars.KEY }} resolves server-side when the run is created. It works in every template site: run commands, env values, agent prompt, model, provider, job runner/name/outputs, step name, and gate feedback. A reference to a missing variable fails run creation with a typed error.

This job fragment belongs under an existing workflow's jobs map:

# yaml-language-server: $schema=https://www.shipfox.io/docs/workflow.schema.json
jobs:
  deploy:
    steps:
      - run: ./deploy.sh --target "${{ vars.DEPLOY_TARGET }}"
      - prompt: >
          Check that ${{ vars.STATUS_URL }} reports healthy after the deploy.

Using secrets

${{ secrets.KEY }} is allowed only in a run step's run command or env values. It is rejected everywhere else: agent prompts, model/provider fields, predicates, and job fields. The optional two-segment form ${{ secrets.local.KEY }} names the built-in local store explicitly.

This job fragment belongs under an existing workflow's jobs map:

# yaml-language-server: $schema=https://www.shipfox.io/docs/workflow.schema.json
jobs:
  publish:
    steps:
      - run: npm publish
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

How a secret reaches the step:

  1. The server never resolves the value. At dispatch, the reference becomes a binding in the step's config. The value is not stored with the run.
  2. The runner pulls the value over a job-scoped, short-lived credential just before the step executes, injects it into the step's process env, and adds it to its masking set.
  3. A reference to a missing secret fails that step with a typed config-unresolvable error. The job does not silently run without it.

Masking

The runner masks secret values in step logs, agent session streams, outputs, annotations, and error messages before anything leaves the machine, including base64, URL-encoded, and hex encodings of the value. Masking reduces exposure, it is not a guarantee. A step that deliberately transforms and prints a secret can still leak it, so treat masking as a safety net, not permission to echo secrets.

Why secrets never reach prompts

Prompts, model responses, and event payloads are inputs to and outputs of a model. Anything placed there can be echoed anywhere the session goes. Keeping secrets structurally out of agent fields (and out of predicates) means no prompt-injection or expression trick can read one. When an agent's work needs a credential (say, pushing a branch), put the credential on a run step in the same job instead.

Variables vs. secrets

VariableSecret
Read back in settings/APIYesNo (write-only)
ResolvesServer, at run creationRunner, at step execution
Allowed inEvery template siteRun-step run and env only
Allowed in predicates (if, filter, gates)NoNo
Masked in logsNoYes (best effort)
Use forURLs, targets, flags, tuningTokens, passwords, keys
Was this page helpful?
Edit this page on GitHub

On this page