Skip to content

fix(sophia): fail closed on ticket-less block submission under ENFORCE (#14588)#7828

Open
Vyacheslav-Tomashevskiy wants to merge 1 commit into
Scottcjn:mainfrom
Vyacheslav-Tomashevskiy:fix/sophia-ticket-bypass
Open

fix(sophia): fail closed on ticket-less block submission under ENFORCE (#14588)#7828
Vyacheslav-Tomashevskiy wants to merge 1 commit into
Scottcjn:mainfrom
Vyacheslav-Tomashevskiy:fix/sophia-ticket-bypass

Conversation

@Vyacheslav-Tomashevskiy

Copy link
Copy Markdown
Contributor

Summary

Fixes the ticket-less block-submission bypass reported in Scottcjn/rustchain-bounties#14588 (High).

api_submit_block() in node/sophia_elya_service.py guarded the Silicon Ticket check with:

if ENFORCE and ticket_id and ticket_id not in tickets_db:
    return jsonify({"error": "invalid_ticket"}), 400

Because ticket_id is falsey when the field is omitted (None) or empty (""), the and ticket_id and clause short-circuits and the tickets_db membership check never runs. A miner could POST a block with header_ext carrying no ticket (or {"ticket": {"ticket_id": ""}}) and pass straight through even with ENFORCE enabled, defeating the ticket-based access control.

Fix

Fail closed — reject when the ticket is missing/empty or unknown, only under enforcement:

if ENFORCE and (not ticket_id or ticket_id not in tickets_db):
    return jsonify({"error": "invalid_ticket"}), 400

Behaviour with ENFORCE off is unchanged, so normal operation is unaffected.

Tests

Added test_elya_submit_block_rejects_missing_ticket_when_enforced covering all three bypass vectors under ENFORCE=True: missing ticket, empty ticket_id, and unknown ticket_id. Verified it fails on the pre-fix code (the ticket-less request slips past the gate into epoch accounting) and passes after the fix (clean 400 invalid_ticket).

$ python3 -m pytest node/tests/test_sophia_elya_service.py -q
10 passed

Two files changed, +42/-1, no dependency or workflow changes.

Closes Scottcjn/rustchain-bounties#14588
/claim #14588

RTC payout address: RTCd1554f0f35576faf01d386a6be1c947f560dd0b7

…E (#14588)

The Silicon Ticket guard in api_submit_block() short-circuited on a falsey
ticket_id:

    if ENFORCE and ticket_id and ticket_id not in tickets_db:

A miner could omit ticket_id (or send an empty string) and skip the
tickets_db membership check entirely, submitting blocks without a valid
ticket even in ENFORCE mode. Guard now fails closed:

    if ENFORCE and (not ticket_id or ticket_id not in tickets_db):

Behaviour with ENFORCE off is unchanged. Adds a regression test covering
missing, empty, and unknown ticket_id under enforcement.
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Welcome to RustChain! Thanks for your first pull request.

Before we review, please make sure:

  • Non-doc PRs have a BCOS-L1 or BCOS-L2 label
  • Doc-only PRs are exempt from BCOS tier labels when they only touch docs/**, *.md, or common image/PDF files
  • New code files include an SPDX license header
  • You've tested your changes against the live node

Bounty tiers: Micro (1-10 RTC) | Standard (20-50) | Major (75-100) | Critical (100-150)

A maintainer will review your PR soon. Thanks for contributing!

@github-actions github-actions Bot added BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) BCOS-L2 Beacon Certified Open Source tier BCOS-L2 (required for non-doc PRs) node Node server related tests Test suite changes size/S PR: 11-50 lines labels Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) BCOS-L2 Beacon Certified Open Source tier BCOS-L2 (required for non-doc PRs) node Node server related size/S PR: 11-50 lines tests Test suite changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

High: Ticket-less Block Submission Bypass in SOPHIA

1 participant