paritytech / paritytech/triangle-js-sdks

Account methods expose cross-product data without JIT permission gating

Open
#134 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug team: sdk
Dominant language
TypeScript
Stars
3
Forks
1
Avg merge
1d 14h
Merged PRs (30d)
8

Description

Summary

host_account_get, host_account_get_alias, and host_account_create_proof accept a caller-supplied ProductAccountId (a (DotNsIdentifier, DerivationIndex) tuple) but are not behind any JIT permission check. A malicious product can invoke these methods with another product's DotNsIdentifier to obtain account public keys, contextual aliases, and ring VRF proofs that belong to a different product's domain — without user awareness or consent.

Affected Methods

Method Input Returns Risk
host_account_get(ProductAccountId) (DotNsIdentifier, DerivationIndex) Account { publicKey, name } Leaks the user's derived public key for an arbitrary product domain
host_account_get_alias(ProductAccountId) (DotNsIdentifier, DerivationIndex) ContextualAlias { context, alias } Leaks the user's ring VRF alias scoped to an arbitrary product domain
host_account_create_proof(ProductAccountId, RingLocation, message) (DotNsIdentifier, DerivationIndex) + ring + message RingVrfProof Generates a valid proof on behalf of the user under an arbitrary product domain

Current Implementation

In host-container, all three are created as plain makeNotImplementedSlot entries with no permission gating:

// packages/host-container/src/createContainer.ts:230-248
const handleAccountGetSlot = makeNotImplementedSlot(
  'host_account_get',
  () => new RequestCredentialsErr.Unknown({ reason: NOT_IMPLEMENTED }),
);

const handleAccountGetAliasSlot = makeNotImplementedSlot(
  'host_account_get_alias',
  () => new RequestCredentialsErr.Unknown({ reason: NOT_IMPLEMENTED }),
);

const handleAccountCreateProofSlot = makeNotImplementedSlot(
  'host_account_create_proof',
  () => new CreateProofErr.Unknown({ reason: NOT_IMPLEMENTED }),
);

Compare with remote_statement_store_submit and remote_preimage_submit, which use makePermissionGatedRequestSlot to enforce RemotePermission checks before the handler is called.

Attack Scenario

  1. Product A (e.g. "malicious.dot") is loaded in the host.
  2. Product A calls host_account_get(["legitimate-product.dot", 0]) — using product B's domain.
  3. The host returns the user's derived public key for product B's domain without prompting the user.
  4. Product A now knows the user's public key in product B's context, enabling cross-product tracking/correlation.
  5. Similarly, host_account_get_alias leaks the user's contextual alias, and host_account_create_proof allows generating proofs under another product's identity.

Suggested Mitigation

Options to consider (not mutually exclusive):

  1. Domain scoping at the container level: The host container should enforce that DotNsIdentifier in the request matches the calling product's registered identity. Requests for other domains should be rejected.
  2. JIT permission prompt: If cross-domain access is a legitimate use case, gate these methods behind a JIT user approval prompt (similar to signing methods returning PermissionDenied/Rejected on denial).
  3. Spec update: The protocol spec (docs/design/host-api-protocol.md) should document the expected host behavior — whether the host MUST restrict ProductAccountId to the calling product's own domain or MUST prompt for cross-domain access.

References

  • Protocol spec: docs/design/host-api-protocol.md (Accounts section, line ~630)
  • Container implementation: packages/host-container/src/createContainer.ts (lines 230-248, 471-485)
  • Codec definitions: packages/host-api/src/protocol/v1/accounts.ts

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with packages/host-container/src/createContainer.ts, comparing the affected account slots with remote_statement_store_submit and remote_preimage_submit, then read the Accounts section of docs/design/host-api-protocol.md and the definitions in packages/host-api/src/protocol/v1/accounts.ts. The work is complete when the intended cross-domain policy is decided, enforced for all three methods, and documented in the protocol spec.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, authorization, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.