design: Altimate Base HTTP registration route isn't bound to real consent (no live exploitation path today)
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- Under an hour
- Newbie friendliness
- 72/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript
Research direction
Read packages/opencode/src/server/server.ts and packages/opencode/src/altimate/free/host.ts, then inspect packages/core/src/altimate-base-disclosure.ts to trace the disclosure and registration flow. Done means a prior disclosure GET from the same caller produces a short-lived, single-use nonce, and registration requires that nonce rather than only the locally computable hash; confirm that sdks/vscode still has no references to the route.
Written by the indexing model from the issue text.
Description
Summary
POST /altimate/base/register (added in #1266 to let non-TUI hosts like the VS Code extension trigger Altimate Base) accepts a hash that any caller can compute locally without ever fetching or displaying the actual disclosure text — so any local process that can reach altimate serve's HTTP port can register Altimate Base, mint a persistent per-install tracking identifier, and opt the install into request/response logging, without the consent dialog ever being shown.
Recalibration (see discussion below): this was initially filed as a security P0 ("any attacker can bypass consent"). On review, that framing overstated it — reaching this endpoint already requires local code execution, and an attacker at that privilege level can automate the TUI dialog just as easily as forming an HTTP POST, and has far more valuable things to do with that access than silently register a free model tier. There is no meaningful capability gained by a malicious local actor that they didn't already have.
The real, narrower issue: the consent gate is a UX affordance, not a security boundary (its own code comment in host.ts says so), and #1266 exposes a route that lets any co-resident, non-malicious process — a future Altimate integration, a CI job, some other local tool — flip a privacy-relevant switch invisibly, with no way for the user to see or decline it. That matters for the feature's informed-consent posture even though nothing malicious is implied. As of today this is a latent design gap, not an active exploit — no shipping client calls this route yet (confirmed: zero references to it in sdks/vscode).
Root cause (verified by tracing the code)
packages/opencode/src/server/server.ts—POST /altimate/base/registercallsFreeTierHost.registerWithAcceptedDisclosure(acceptedDisclosureSha256).packages/opencode/src/altimate/free/host.ts:79-88— this checks the supplied hash againstFreeTierConsent.disclosureHash().packages/core/src/altimate-base-disclosure.ts:15-16—disclosureHash()is a SHA-256 of a public, hardcoded string. Any caller can compute this locally without ever callingGET /altimate/base/disclosure, let alone rendering it to a person.
There is no session/UI-provenance check, no interactive-confirmation flag, nothing binding the POST to a human having actually read anything.
Proposed fix (scoped, <30 min, no design work)
Bind POST /altimate/base/register to a prior GET /altimate/base/disclosure call from the same caller via a short-lived, single-use nonce that must be echoed back on the register call. This doesn't prove a human read the screen, but it closes the "compute the public hash and skip the GET entirely" gap for any non-malicious co-resident caller, which is the actual risk here.
Provenance
Found during the v0.11.0 stable release's Chaos Gremlin (privacy/compliance) persona review. Deliberately shipped in v0.11.0 as an explicit, user-reviewed risk acceptance (recalibrated to a design-gap/P1, not a blocking security P0) — recorded here so the fix isn't lost.
- Dominant language
- TypeScript
- Stars
- 813
- Forks
- 134
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 65
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from AltimateAI/altimate-code
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
AltimateAI/altimate-code#1359 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
AltimateAI/altimate-code#1323 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
AltimateAI/altimate-code#1288 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 92/100
AltimateAI/altimate-code#1285 ·
-
privacy: Altimate Base consent dialog no longer discloses persistent per-installation identifier Open
Difficulty 1/5 Under an hour Newbie friendliness 88/100
AltimateAI/altimate-code#1284 ·
All issues in AltimateAI/altimate-code
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
bcgov/bc-wallet-mobile#4761 · 1 comment ·
-
external-issue to-triage
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
area-deployment area-integrations triage:bot-seen
Difficulty 2/5 Half a day Newbie friendliness 86/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
refactor
Difficulty 2/5 1-3 hours Newbie friendliness 84/100