Skip to content

3491 vulncheck api token fallback - #335

Open
robc-vulncheck wants to merge 5 commits into
mainfrom
3491-vulncheck-api-token-fallback
Open

3491 vulncheck api token fallback#335
robc-vulncheck wants to merge 5 commits into
mainfrom
3491-vulncheck-api-token-fallback

Conversation

@robc-vulncheck

@robc-vulncheck robc-vulncheck commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Accept VULNCHECK_API_TOKEN as a fallback token variable

resolves https://github.com/vulncheck/product/issues/3491

The cli was the only VulnCheck client reading VC_TOKEN - the SDKs and MCP server use VULNCHECK_API_TOKEN. The cli now accepts either.

As per 3491, VC_TOKEN remains primary to avoid any breaking change, with VULNCHECK_API_TOKEN as a fallback - so now users can set one env var for all the open source products. VULNCHECK_API_TOKEN is now the documented name, but VC_TOKEN wins when both are set (to avoid changing behaviour for existing users), and an exported VULNCHECK_API_TOKEN is used above the config-file login, as VC_TOKEN already did.

Some changes unrelated to the env var change:

  • ef2039a - tokens are trimmed wherever they come from (env, config file, and on save). Strips trailing spaces etc
  • fdf8592 - the tests now stub the API instead of hitting production. Needed for the new tests, which assert on auth outcomes and so need a deterministic 401/200.

go test ./... green, vet and gofmt clean. Precedence matrix verified against a live token.

The CLI read only VC_TOKEN while the SDKs and MCP server read
VULNCHECK_API_TOKEN, so anyone moving between them hit an auth failure with
a perfectly good token already exported.

Resolve() now scans VC_TOKEN then VULNCHECK_API_TOKEN before the config
file. VC_TOKEN keeps precedence, so no existing setup changes which
credential it uses.

Every message that named a token variable hardcoded config.EnvToken, which
becomes a lie for anyone who set only the documented name. Resolution now
carries EnvVar (the variable in use) and EnvVarsSet (every variable holding
a usable token, EnvVarsSet[0] == EnvVar), and the login, logout, status and
error-hint sites render from those. auth status --json reports the variable
as token_env_var.

Hints clear every variable via UnsetHint rather than the winner alone:
clearing only the winner hands the win to the next one and the attempt is
refused all over again. UnsetHint is shell-neutral because `unset` is not a
command on Windows, which the CLI ships binaries for.

GuardEnvToken's refusal is reworded: anyone running the CLI beside an SDK
has the variable exported on purpose, and telling them to clear it framed a
working setup as a failure.

Refs #3491
`export VULNCHECK_API_TOKEN=$(cat /run/secrets/token)`, a Docker or
Kubernetes secret mounted as a file, or a sourced .env all deliver the token
with its trailing newline attached. ValidToken already trimmed before
deciding a value was usable, but Resolve stored the raw string, so the
padded value reached net/http and was refused as an invalid Authorization
header value — surfacing as code "internal" at exit 1, naming no variable.
An agent branching on the auth codes read a fixable credential problem as a
CLI bug. A trailing space was worse: it survives the header and comes back
as a plain 401 on a perfectly good token.

Trim on capture in all three positions — both environment variables, the
config file on read, and SaveToken on write. A padded paste written to
vulncheck.yaml verbatim fails every later run, and unlike an environment
variable the user cannot see it to fix it.

Trimming on read also stops Shadowed reporting a conflict between two
whitespace-different spellings of one token.

This predates the VULNCHECK_API_TOKEN fallback and affects VC_TOKEN
identically; the fallback makes it far more likely to be hit, since the
documented name is the one container, MCP and secret-file workflows use.
In CI with a token variable already exported, `auth login` returned
"cannot be run in a CI environment, use the VULNCHECK_API_TOKEN environment
variable instead" — advising the user to set the variable that is already
set. The interactivity check ran before GuardEnvToken, so the guard never
got to say that the CLI is already authenticating with it.

Swap the two. With no token set, CI behaviour is unchanged.

Predates the VULNCHECK_API_TOKEN fallback: on VC_TOKEN alone,
`CI=1 VC_TOKEN=... vulncheck auth login` shows the same thing.
VULNCHECK_API_TOKEN is the name the SDKs and MCP server already document,
so it becomes the one the CLI teaches: the README environment table, the
GitHub Actions and CI help, `auth login` help, the no-token error and the
CI refusal. VC_TOKEN is documented as the legacy alias that keeps
precedence, so no existing setup is invalidated.

The Actions snippet names a secret the reader has to substitute, and says
so: vulncheck-oss/action documents a VC_TOKEN secret, and a secret that
does not exist expands to an empty string, which reads here as no token at
all — landing the user back on "No token found" with nothing to go on.

Refs #3491
@robc-vulncheck
robc-vulncheck force-pushed the 3491-vulncheck-api-token-fallback branch from 803866b to a48354e Compare September 4, 2026 16:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant