---
title: Environment variables and subprocess behaviour
description: Every environment variable rtb-forge reads or sets, the exact git commands it runs, and the HTTP headers it sends.
tags: [reference, environment, security]
---
# Environment variables and subprocess behaviour
## Which environment variables does `rtb-forge` set?
| `RTB_VCS_GIT_TOKEN` | the `git` subprocess for authenticated `clone`, `fetch`, `push` | the resolved secret | Carries the password to the inline credential helper without putting it in argv |
| `GIT_TERMINAL_PROMPT` | the `git` subprocess for `clone`, `fetch`, `push` | `0` | Makes an auth failure exit non-zero immediately instead of blocking on a prompt |
Both are set on the child process only. Neither is read from or written to the
parent process environment.
### The name is `RTB_VCS_GIT_TOKEN`, not `RTB_FORGE_GIT_TOKEN`
The crate was renamed from `rtb-vcs` to `rtb-forge` at extraction from the
rust-tool-base monorepo. The variable name was deliberately left alone, because
it is part of the runtime contract with anything that inspects the subprocess
environment. Do not expect an `RTB_FORGE_`-prefixed alias; there is none.
You do not set this variable yourself. It is written by `rtb-forge` onto the
child process. Where *your* token comes from is decided by the `CredentialRef`
you attach to the options struct (see
[Authenticate git operations](../how-to/02-authenticate-git-operations.md)).
### `GIT_TERMINAL_PROMPT` is not set for `checkout` or `commit`
Only the three network operations set it. `Repo::commit` and `Repo::checkout`
inherit the parent environment unchanged, so if something in that environment
causes `git` to prompt, those calls can block. In a service, set
`GIT_TERMINAL_PROMPT=0` process-wide.
## What exactly does the credential helper do?
Authenticated operations pass this to `git` as `-c credential.helper=<value>`:
```sh
!f() { echo username=x-access-token; echo password=$RTB_VCS_GIT_TOKEN; }; f
```
The snippet contains no secret. It reads one from the environment at the
moment git asks. Three properties follow:
- The secret never appears in argv, so it is not visible in `ps` output.
- The secret is never written to a temporary file or to `~/.git-credentials`.
- The helper is scoped to the single invocation via `-c`; it does not modify
any repository or global git config.
**The username is hard-coded to `x-access-token`.** That is GitHub's
personal-access-token convention, and GitLab and Gitea accept it for
token-based auth too. There is no configuration hook to change it. A forge that
requires a real username with a token cannot be authenticated through
`Repo::clone` / `fetch` / `push`; wrap the operation yourself.
## Which git commands are run?
Exactly these, always with the repository directory (`Repo::path()`) as the
working directory, except `clone` which takes the destination as an argument:
| `clone` (anonymous) | none (pure gix) |
| `clone` (authenticated) | `git -c credential.helper=<helper> clone -- <url> <dst>` |
| `fetch` (anonymous) | `git fetch <remote>` |
| `fetch` (authenticated) | `git -c credential.helper=<helper> fetch <remote>` |
| `checkout` | `git checkout [--force] <revspec>` |
| `commit` | `git add -- <paths…>`, then `git commit -m <message>`, then `git rev-parse HEAD` |
| `push` (anonymous) | `git push <remote> <refspec>` |
| `push` (authenticated) | `git -c credential.helper=<helper> push <remote> <refspec>` |
The `--` separators on `clone` and `add` stop a URL or path beginning with `-`
being read as a flag.
Nothing runs through a shell. Every command is spawned directly with
`std::process::Command`, so shell metacharacters in a URL, path, remote name or
refspec are not interpreted. The credential-helper string is a shell snippet,
but it is `git` that evaluates it, not `rtb-forge`.
stdout is captured and discarded except for `git rev-parse HEAD`, whose output
becomes the commit OID. stderr is captured, trimmed, and placed in the `cause`
field of the corresponding `RepoError`. **A failing git command's stderr can
therefore end up in your logs**. It will not contain the token, because the
token is only ever in the environment, but it may contain a repository URL.
## Which HTTP headers do the release backends send?
Every REST backend builds its `reqwest` client the same way:
| `https_only` | `true` |
| `User-Agent` | `rtb-forge/<crate version>`, for example `rtb-forge/0.7.1` |
| `timeout` | `timeout_seconds` seconds, or unset when it is `0` |
Per-request headers:
| GitHub | `Authorization: Bearer <token>` | `Accept: application/vnd.github+json`, `X-GitHub-Api-Version: 2022-11-28`; `Accept: application/octet-stream` on downloads |
| GitLab | `PRIVATE-TOKEN: <token>` | `Accept: application/json` |
| Gitea / Codeberg | `Authorization: token <token>` | `Accept: application/json` |
| Bitbucket | HTTP Basic, `username` + token | `Accept: application/json` |
| Direct | `Authorization: Bearer <token>` | — |
The auth header is only added when a token was passed to the factory (and, for
Bitbucket, only when `username` is also set). The `private` config key does not
affect this.
## Is plain HTTP ever possible?
Not from configuration. Every parameter struct carries an
`allow_insecure_base_url` field, but it is `#[serde(skip)]`, so no config file
(YAML, TOML, environment overlay) can set it. It exists so the crate's own
tests can point a provider at a local wiremock or testcontainer, and it does
two things when set in Rust code: builds the client without `https_only`, and
constructs URLs with the `http://` scheme.
The GitHub backend also refuses any host that literally begins
`http://`, regardless of the flag.
## Does anything read the ambient environment?
The release-provider slice reads nothing: no proxy variables of its own, no
token discovery, no config file lookup. `reqwest` applies its own defaults,
which include honouring the system proxy environment.
The git slice reads the environment only through the tools it invokes: `gix`
and `git` both resolve `user.name`, `user.email`, `init.defaultBranch`, proxy
settings and everything else from git's normal configuration cascade. Credential
resolution is delegated to `rtb-credentials`, whose `CredentialRef` may name
environment variables to read. That is your configuration, not this crate's.