fix(list-secrets): mask secret values by default (opt-in via includeValues) - #22
fix(list-secrets): mask secret values by default (opt-in via includeValues)#22Shyrka973 wants to merge 1 commit into
Conversation
|
| Filename | Overview |
|---|---|
| src/index.ts | Adds includeValues boolean parameter (default false) to list-secrets, introduces a mapSecret helper to conditionally strip secretValue, and surfaces a valuesMasked flag in the response. Masking is correctly applied to both top-level secrets and imported secrets via the shared helper. |
Reviews (1): Last reviewed commit: "fix(list-secrets): mask secret values by..." | Re-trigger Greptile
|
✅ CLA satisfied. All contributors have signed the current CLA. The |
…alues)
Add a new `includeValues` boolean parameter to `list-secrets`, defaulting
to false. When false (the default), the response only contains `secretKey`
for each secret; the `secretValue` field is omitted entirely. Callers that
genuinely need values must explicitly pass `includeValues: true`.
Why
---
The previous behavior unconditionally serialized `secretValue` for every
secret in the path. Because this MCP is consumed by LLMs (Claude, GPT,
etc.), a single `list-secrets` invocation typically deposits the entire
path's values into the model's context window and from there into the
provider's logs for the duration of their retention policy.
This is asymmetric vs `get-secret`, which requires the caller to name the
secret it wants (leaks are bounded). `list-secrets` is exploratory by
design — agents call it when they don't yet know what's there, which is
exactly when they shouldn't see values.
Also add a `valuesMasked: <bool>` flag to the response so agents can
self-detect whether they've received only keys.
Tested
------
- Syntax: `node --check dist/index.js` OK
- Unit: mapper isolated; `includeValues=false` -> `{secretKey: X}`,
`includeValues=true` -> `{secretKey: X, secretValue: ...}`
- Live stdio (real Infisical instance):
- default -> response has `valuesMasked: true`, no `secretValue` field
- `includeValues: true` -> response has `valuesMasked: false`, full values
This is a breaking change for callers relying on `secretValue` being
present unconditionally; suggest bumping to 0.1.0 in the release.
d362272 to
ee59040
Compare
|
CLA signed — all checks are green now. Flagging this as ready for review. It closes #21, and has been running as a patched local build in my environment since May with no issues. (I force-pushed earlier today to correct a wrong author email on the commit — the CLA bot was attributing it to someone else's account. The diff is unchanged.) Happy to add tests if you'd like — the repo has no suite today, so let me know which framework you'd prefer. |
|
Just spent some time realising the same issue with using this MCP, I would consider this a critical security patch. Although there are other ways to secure infisical from exposing keys/values. This should be in place by default as a defensive security measure as misconfiguration could expose sensitive vars to the LLM. Giving this a bump, thanks for the work @Shyrka973! @varonix0 Is this something you can take a look at soon? |
Closes #21.
What
Add an
includeValues: booleanparameter (defaultfalse) tolist-secrets. When false, the response only containssecretKeyfor each secret; thesecretValuefield is omitted entirely. Also add avaluesMasked: <bool>flag to the response for agent self-introspection.Why
See #21 for the full rationale. TL;DR:
list-secretsis consumed by LLMs and unconditionally returningsecretValuecauses accidental leaks to provider logs on every exploratory call.get-secretdoesn't have this issue because the caller names what it wants.Changes
Single file:
src/index.ts(+15/-9 lines).includeValues: z.boolean().default(false)inputSchema.properties): addincludeValuesfield with safety-oriented descriptionmapSecrethelper that conditionally includessecretValuebased ondata.includeValuesvaluesMasked: !data.includeValuesflagTesting
Tested at three levels before opening this PR:
node --check dist/index.js→ OK afternpm run buildincludeValues=false→{secretKey: "X"}.includeValues=true→{secretKey: "X", secretValue: "..."}list-secretson a path with 2 known secrets:includeValues→ response:{"valuesMasked":true,"secrets":[{"secretKey":"OPENAI_API_KEY"},{"secretKey":"OAUTH_CLIENT_SECRET"}]}includeValues: true→ response:{"valuesMasked":false,"secrets":[{"secretKey":"OPENAI_API_KEY","secretValue":"..."},{"secretKey":"OAUTH_CLIENT_SECRET","secretValue":"..."}]}This patched binary has been deployed locally as a workaround in my environment since 2026-05-26.
The repo has no test suite, so I've stopped here — happy to add one if you'd like guidance on the framework you'd prefer.
Backward compatibility
This is a breaking change for callers that relied on values being present unconditionally. As discussed in #21, I'd suggest bumping to
0.1.0to signal the change.Related
removeAccessTokenfrom error messages. Could be reviewed/merged together.