[GH-ISSUE #6549] [Bug] IDA registration_digest commits to header and environment credential values #3939

Closed
opened 2026-10-31 00:45:24 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @Adolanium on GitHub (Oct 23, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/6549

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Provider or capability discovery

Observed behavior

The IDA analysis profile's registration_digest is a SHA-256 of the whole IDA MCP registration, including HTTP headers and stdio env values. Those values hold transport credentials (for example Authorization: Bearer … or an API key variable). The profile is returned with analysis results and retained in Evidence, so it commits to the secret: a candidate token can be confirmed against the digest, and rotating a token changes the profile identity.

Reproduction

Ran on Linux (WSL Ubuntu, Node 24.22.1) at upstream/main 6c4d880f2, in a test that resolves real profiles:

  1. Write two IDA registrations that differ only in the bearer token value ({"url": "http://127.0.0.1:8745/mcp", "mode": "headless", "headers": {"Authorization": "Bearer first-token"}} and the same with second-token).
  2. Point REA_IDA_MCP_CONFIG at each and call IdaProvider.resolveAnalysisProfile.
  3. On upstream/main the two registration_digest values differ, so the digest depends on the token value. The same holds for stdio env values.

Expected behavior

Values the registration marks as secret do not reach the digest. Every other value, including non-secret headers / env values such as IDADIR, still distinguishes registrations, and a changed secret still starts a new client rather than reusing the old connection.

Impact and scope

Anyone who receives an IDA analysis result or retained Evidence can test guesses for the configured token or key against the digest. Short or reused tokens are exposed this way. IDA provider only.

REA version

6.7.0, revision 6c4d880f2

Runtime and platform

Linux (WSL Ubuntu), Node 24.22.1

Target and artifact context

No target; the profile is resolved from the registration alone.

Interface

MCP

Earliest failure stage

Setup or provider admission

Relevant output or evidence

src/ida/IdaProvider.ts, resolveAnalysisProfile:

registration_digest: createHash("sha256")
  .update(canonicalize(config.value) ?? "")
  .digest("hex"),

Typed outcome or recovery expected

No new error. A registration can mark its secret headers / env entries; only those values are withheld from the digest.

Analysis or suspected cause

The digest hashes the parsed registration as a whole, and the registration schema keeps credential-bearing headers and env values in it. AGENTS.md asks REA to redact transport authentication credentials.

Additional context

Fixed by #6548.

Originally created by @Adolanium on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6549 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Provider or capability discovery ### Observed behavior The IDA analysis profile's `registration_digest` is a SHA-256 of the whole IDA MCP registration, including HTTP `headers` and stdio `env` values. Those values hold transport credentials (for example `Authorization: Bearer …` or an API key variable). The profile is returned with analysis results and retained in Evidence, so it commits to the secret: a candidate token can be confirmed against the digest, and rotating a token changes the profile identity. ### Reproduction Ran on Linux (WSL Ubuntu, Node 24.22.1) at upstream/main 6c4d880f2, in a test that resolves real profiles: 1. Write two IDA registrations that differ only in the bearer token value (`{"url": "http://127.0.0.1:8745/mcp", "mode": "headless", "headers": {"Authorization": "Bearer first-token"}}` and the same with `second-token`). 2. Point `REA_IDA_MCP_CONFIG` at each and call `IdaProvider.resolveAnalysisProfile`. 3. On upstream/main the two `registration_digest` values differ, so the digest depends on the token value. The same holds for stdio `env` values. ### Expected behavior Values the registration marks as secret do not reach the digest. Every other value, including non-secret `headers` / `env` values such as `IDADIR`, still distinguishes registrations, and a changed secret still starts a new client rather than reusing the old connection. ### Impact and scope Anyone who receives an IDA analysis result or retained Evidence can test guesses for the configured token or key against the digest. Short or reused tokens are exposed this way. IDA provider only. ### REA version 6.7.0, revision `6c4d880f2` ### Runtime and platform Linux (WSL Ubuntu), Node 24.22.1 ### Target and artifact context No target; the profile is resolved from the registration alone. ### Interface MCP ### Earliest failure stage Setup or provider admission ### Relevant output or evidence `src/ida/IdaProvider.ts`, `resolveAnalysisProfile`: ```ts registration_digest: createHash("sha256") .update(canonicalize(config.value) ?? "") .digest("hex"), ``` ### Typed outcome or recovery expected No new error. A registration can mark its secret `headers` / `env` entries; only those values are withheld from the digest. ### Analysis or suspected cause The digest hashes the parsed registration as a whole, and the registration schema keeps credential-bearing `headers` and `env` values in it. AGENTS.md asks REA to redact transport authentication credentials. ### Additional context Fixed by #6548.
Author
Owner

@XinwangTao commented on GitHub (Oct 23, 2026):

Good catch — hashing the full registration means the digest acts as a confirmation oracle for any guessed Authorization header or env value, and since the profile (with digest) is retained in Evidence, the secret leak outlives the transport session. Excluding header/env values while keeping names, URL, command and mode as digest inputs preserves identity for everything that matters (transport config, provenance) without leaking the credentials themselves. Agree with the #6548 direction; worth adding a regression test where two registrations differing only in token value produce identical digests, and one differing in URL or command still diverge.

<!-- gh-comment-id:6360798680 --> @XinwangTao commented on GitHub (Oct 23, 2026): Good catch — hashing the full registration means the digest acts as a confirmation oracle for any guessed Authorization header or env value, and since the profile (with digest) is retained in Evidence, the secret leak outlives the transport session. Excluding header/env values while keeping names, URL, command and mode as digest inputs preserves identity for everything that matters (transport config, provenance) without leaking the credentials themselves. Agree with the #6548 direction; worth adding a regression test where two registrations differing only in token value produce identical digests, and one differing in URL or command still diverge.
Author
Owner

@Adolanium commented on GitHub (Oct 23, 2026):

Thanks. One change since this comment: #6548 no longer drops every headers and env value. That broke two things, so it was reworked.

  • Non-secret values such as IDADIR or a backend-selecting header stopped distinguishing profiles.
  • The session reuses a live client when the profile is unchanged, so a rotated token kept the old connection.

Now a registration lists its secret entries in an optional sensitive array. AGENTS.md asks REA not to infer secrecy from names. Only those values are replaced in registration_digest. The complete registration is kept as a private binding key that is never serialized, and the session compares it before reusing a client.

The tests cover what you suggested. With Authorization marked, two registrations that differ only in the token give the same digest but different binding keys. A changed unmarked header, or a different IDADIR, changes the digest. URL and command still feed the digest as before; the tests don't vary them separately. The PR stays a draft until a maintainer decides on the sensitive field.

<!-- gh-comment-id:6366787226 --> @Adolanium commented on GitHub (Oct 23, 2026): Thanks. One change since this comment: #6548 no longer drops every `headers` and `env` value. That broke two things, so it was reworked. - Non-secret values such as `IDADIR` or a backend-selecting header stopped distinguishing profiles. - The session reuses a live client when the profile is unchanged, so a rotated token kept the old connection. Now a registration lists its secret entries in an optional `sensitive` array. AGENTS.md asks REA not to infer secrecy from names. Only those values are replaced in `registration_digest`. The complete registration is kept as a private binding key that is never serialized, and the session compares it before reusing a client. The tests cover what you suggested. With `Authorization` marked, two registrations that differ only in the token give the same digest but different binding keys. A changed unmarked header, or a different `IDADIR`, changes the digest. URL and command still feed the digest as before; the tests don't vary them separately. The PR stays a draft until a maintainer decides on the `sensitive` field.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3939
No description provided.