security: profile page renders unsanitized ENS-supplied URL
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 11
- Forks
- 26
- Avg merge
- 11h 58m
- Merged PRs (30d)
- 16
Description
Summary
The orchestrator profile renders an external website link directly from identity.url, which is sourced from the orchestrator's ENS url text record. ENS text records are user-controlled, so this value is fully attacker-controlled for any account whose ENS profile is configured.
See components/Profile/index.tsx:279:
{identity?.url && (
<A
variant="contrast"
css={{ fontSize: "$2" }}
href={identity.url}
target="__blank"
rel="noopener noreferrer"
>
...
{identity.url.replace(/(^\w+:|^)\/\//, "")}
</A>
)}
Attack vectors
A malicious orchestrator can set their ENS url text record to:
javascript:alert(document.cookie)— when a viewer clicks the globe link, arbitrary JS runs in the explorer origin. React 16+ logs a warning forjavascript:hrefs but does not reliably block them, especially after build-time minification.data:text/html,<script>...</script>— opens a same-document data URL whose script can phish or impersonate the explorer.evil.com/path(no scheme) — the browser treats this as a relative path, so the link navigates tohttps://explorer.livepeer.org/.../evil.com/pathinstead of the intended external site. Useful for bait-and-switch / phishing where the displayed text and the actual destination differ.
Scope
Only the website (identity.url) field is affected. The Twitter and GitHub blocks just below it interpolate the user value into hardcoded https://twitter.com/... / https://github.com/... URLs, so the protocol is fixed and they are not the same risk.
Fix
Validate the URL before rendering: auto-prefix https:// if no scheme is present, parse via new URL(...), and reject anything where protocol is not http: or https:. If sanitization fails, do not render the link block at all. Bind the sanitized value to both href and title so the user sees what they will actually navigate to.
Fix is in #644.
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.
Research direction
The affected code is components/Profile/index.tsx around line 279, where identity.url is rendered. Review the validation described in the issue and compare the existing implementation with pull request #644; done means unsafe schemes are not rendered and accepted links use the sanitized destination consistently.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend, security
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 20/100