Skip to content
This repository was archived by the owner on May 11, 2026. It is now read-only.

fix: ensure alias can only be linked to a single address#630

Merged
wa0x6e merged 11 commits into
masterfrom
fix/alias-single-address
Apr 4, 2026
Merged

fix: ensure alias can only be linked to a single address#630
wa0x6e merged 11 commits into
masterfrom
fix/alias-single-address

Conversation

@wa0x6e

@wa0x6e wa0x6e commented Mar 16, 2026

Copy link
Copy Markdown
Contributor

Summary

An alias could previously be linked to multiple addresses, allowing different users to claim the same alias. This PR adds a server-side check in verify() to reject alias creation when the alias is already linked to a different address, while still allowing the same address to renew its existing alias.

Changes

  • verify(): rejects when alias is linked to a different address (single SQL query with AND address != ?)
  • action(): uses ON DUPLICATE KEY UPDATE for renewals (from master via PR fix: allow alias renewal by re-submitting existing pair #629)
  • ✅ Added UNIQUE KEY on aliases.alias in test schema
  • ✅ Updated fixtures to avoid UNIQUE KEY collision
  • ✅ Integration test for cross-address alias rejection
  • ✅ Unit test with DB mock since verify() now queries the DB

Database migration

Run the following on the production database to enforce uniqueness at the DB level:

ALTER TABLE aliases ADD UNIQUE KEY alias (alias);

Test plan

  • yarn test:unit — alias unit tests pass with mocked DB
  • yarn test:integration — alias integration tests pass, including new cross-address rejection test
  • yarn test:e2e — existing e2e tests unaffected

Adds a duplicate check in the alias writer's verify() step to return
a clear error instead of relying on the DB primary key constraint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wa0x6e
wa0x6e force-pushed the fix/alias-single-address branch 3 times, most recently from 2bb4b30 to 86030c7 Compare March 16, 2026 10:32

@ChaituVR ChaituVR left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add Unique index on DB instead of a check on application, wyt?

Adds a check that rejects alias creation if the alias address is
already associated with a different parent address, preventing
one alias from acting on behalf of multiple addresses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wa0x6e
wa0x6e force-pushed the fix/alias-single-address branch from 86030c7 to b9e5ff4 Compare March 17, 2026 08:22
@wa0x6e

wa0x6e commented Mar 17, 2026

Copy link
Copy Markdown
Contributor Author

I think we should add Unique index on DB instead of a check on application, wyt?

Added

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR closes snapshot-labs/workflow#767 by enforcing a 1:1 relationship between an alias address and its parent address (preventing one alias from acting on behalf of multiple identities), using both an application-level pre-check and a DB-level uniqueness constraint.

Changes:

  • Updated alias writer verification to reject alias creation when the alias is already linked (either to the same address or a different one) using a single lookup by alias.
  • Added a UNIQUE KEY on the aliases.alias column in the test schema to enforce 1:1 alias ownership at the database level.
  • Added an integration test covering the “alias already linked to another address” rejection path (and adjusted fixtures to satisfy the new uniqueness constraint).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/writer/alias.ts Consolidates alias existence checks into a single query by alias and introduces new rejection message for cross-address conflicts.
test/schema.sql Adds a unique index on aliases.alias to enforce one alias per table globally.
test/integration/helpers/alias.test.ts Adds integration coverage for rejecting alias reuse across different parent addresses.
test/fixtures/alias.ts Updates fixture data to avoid collisions under the new unique index.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread test/schema.sql
Comment thread src/writer/alias.ts Outdated
Comment thread src/writer/alias.ts Outdated
@wa0x6e
wa0x6e force-pushed the fix/alias-duplicate-check branch 2 times, most recently from 0ebe3fc to 03c0842 Compare March 17, 2026 13:01
@wa0x6e
wa0x6e force-pushed the fix/alias-duplicate-check branch 7 times, most recently from ee57600 to 0beb198 Compare March 28, 2026 03:11
Allow the same (address, alias) pair to be submitted again to refresh
the expiration. Uses ON DUPLICATE KEY UPDATE to reset created timestamp.
@wa0x6e
wa0x6e force-pushed the fix/alias-duplicate-check branch from 0beb198 to d7424ee Compare March 28, 2026 03:12
@wa0x6e

wa0x6e commented Mar 30, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix the merge conflict

Copilot AI and others added 4 commits March 30, 2026 09:41
Co-authored-by: wa0x6e <495709+wa0x6e@users.noreply.github.com>
Co-authored-by: wa0x6e <495709+wa0x6e@users.noreply.github.com>
Co-authored-by: wa0x6e <495709+wa0x6e@users.noreply.github.com>
This reverts commit 6bf2457.

Co-authored-by: wa0x6e <495709+wa0x6e@users.noreply.github.com>

Copilot AI commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

@copilot fix the merge conflict

Fixed in 311c88d. Merged the updated base branch (which added alias renewal via ON DUPLICATE KEY UPDATE) into our branch. The combined result:

  • verify() now only rejects when the alias is linked to a different address, allowing same-address renewal (case-insensitive comparison)
  • action() uses ON DUPLICATE KEY UPDATE from the base branch to handle renewals
  • Unit test updated with a DB mock since verify() now queries the DB

Base automatically changed from fix/alias-duplicate-check to master April 1, 2026 13:01
@wa0x6e

wa0x6e commented Apr 1, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix the merge conflict

Co-authored-by: wa0x6e <495709+wa0x6e@users.noreply.github.com>

Copilot AI commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

@copilot fix the merge conflict

Fixed in afb57c4. The base branch fix/alias-duplicate-check was merged into master as PR #629, so I merged master into this branch to resolve the conflict. The diff vs master now only shows our changes: the cross-address check in verify(), the UNIQUE KEY in the test schema, the fixture update, and the tests.

wa0x6e added 2 commits April 1, 2026 23:48
jest.mock doesn't work with jest-environment-node-single-context
since the mysql module is already loaded by globalSetup.
@ChaituVR

ChaituVR commented Apr 2, 2026

Copy link
Copy Markdown
Member

Looks good to me, except there are currently 120 alias addresses linked to multiple owners in the DB

SELECT alias, COUNT(DISTINCT address) as owner_count, 
  MIN(FROM_UNIXTIME(created)) as first_created, 
  MAX(FROM_UNIXTIME(created)) as last_created 
FROM aliases 
GROUP BY alias 
HAVING owner_count > 1 
ORDER BY owner_count DESC, last_created DESC

How do we handle this before running the ALTER TABLE aliases ADD UNIQUE KEY alias (alias); ?

@wa0x6e

wa0x6e commented Apr 3, 2026

Copy link
Copy Markdown
Contributor Author

We did not prevent multiple alias before this PR, and allows multiple addresses using the same alias.

Aliases generation on our UI should generate a new alias each time, and never reuse, so those duplicate probably come from people who set them via API, and use this a kind of delegation system, the duplicate alias was a feature. Changing the behavior to be unique will probably break their integration.

On the other hand, with the new UI page for creating alias, with the alias address only set via the URL, anybody can set an alias address they control in the url, and share this page. Once an user sign this page without paying attention (because this alias address is new to him), he hereby authorize this alias to act on his behalf.

Merging this PR may break integration for the existing integrator using it as a delegation system, but not merging it may expose the alias to phishing attacks.

The patch should probably be on the UI alias creation page, and make the page params more robust by adding a verification message signed the alias wallet, and be time sensitive (more robust way would be to also include the aliased address in the verification message)

@ChaituVR

ChaituVR commented Apr 3, 2026

Copy link
Copy Markdown
Member

Oh yes i agree. but what i meant was that if we run ALTER TABLE aliases ADD UNIQUE KEY alias (alias); it will fail no? because there's already duplicate data, what do we do with the data 🙈

@wa0x6e

wa0x6e commented Apr 3, 2026

Copy link
Copy Markdown
Contributor Author

Maybe not go with the PR, as duplication is widely used as a feature

@ChaituVR

ChaituVR commented Apr 3, 2026

Copy link
Copy Markdown
Member

But the phishing attack you mentioned is super valid 🙈 Maybe we can ignore uniqueness at SQL level and still check in app level? so weird that so many already use the alias system in wrong way. 🙈 not sure what's the right way to handle this. maybe we need need two signatures (one from user and one from alias as you suggest) which are signed at same time, to prove both belong to same user?

@wa0x6e

wa0x6e commented Apr 3, 2026

Copy link
Copy Markdown
Contributor Author

Duplicates have been removed from the database, they were not genuine.

Database has also been updates with the new index

@ChaituVR ChaituVR left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tAck

@wa0x6e
wa0x6e merged commit a89b48b into master Apr 4, 2026
2 checks passed
@wa0x6e
wa0x6e deleted the fix/alias-single-address branch April 4, 2026 13:52
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants