Skip to content

Fix election isolation security#42

Merged
grunch merged 2 commits intomainfrom
fix-election-isolation-security
Jul 7, 2025
Merged

Fix election isolation security#42
grunch merged 2 commits intomainfrom
fix-election-isolation-security

Conversation

@grunch
Copy link
Collaborator

@grunch grunch commented Jul 7, 2025

Summary by CodeRabbit

  • Documentation

    • Added comprehensive technical documentation detailing Nostr protocol integration for decentralized voting, including event types, message formats, flow diagrams, relay configuration, and security considerations.
    • Expanded and clarified the README section on Nostr integration, outlining its roles and referencing the new protocol documentation.
  • New Features

    • Introduced example scripts for creating and debugging elections via gRPC, including voter management and election inspection.
  • Bug Fixes

    • Improved error handling and logging for token requests and vote submissions, distinguishing between election-specific and legacy protocols.
  • Refactor

    • Enhanced message structures to include optional election identifiers for improved election-specific validation and backward compatibility.
  • Tests

    • Added unit tests to verify election isolation and voter authorization across multiple elections.

grunch added 2 commits July 7, 2025 15:00
- Add election_id field to Message structure for election-specific validation
- Update EC logic to validate token requests and votes for specific elections
- Enhance voter client to include election_id in all requests
- Add comprehensive tests for election isolation
- Maintain backward compatibility with legacy message format
- Prevent cross-election voting and unauthorized access

Security Impact:
- Fixes vulnerability where voters could vote in elections they weren't registered for
- Ensures proper election isolation and voter authorization
- Maintains database integrity with election-specific token tracking
@grunch
Copy link
Collaborator Author

grunch commented Jul 7, 2025

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 7, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 7, 2025

Walkthrough

This update introduces a comprehensive technical specification for Nostr protocol integration in Criptocracia via a new NOSTR.md document, expands related details in the README, and implements election-specific message handling in both the election commission (EC) and voter codebases. New Rust example and debug scripts are added, and the Message struct is extended with an optional election_id field for improved election isolation and backward compatibility.

Changes

File(s) Change Summary
NOSTR.md Added a detailed technical specification for Nostr protocol integration, event kinds, message formats, flows, and security details.
README.md Expanded and clarified the Nostr protocol integration section; added reference to NOSTR.md.
ec/examples/create_1b3c.rs New Rust example: creates an election and adds a voter using gRPC admin client.
ec/examples/debug_1b3c.rs New Rust debug script: inspects election "1b3c" and its voters via gRPC.
ec/src/election.rs Added unit tests for election isolation; derived Clone for BlindTokenRequest to support tests.
ec/src/main.rs Modified control flow for token requests and vote submissions: supports election-specific and legacy protocols with enhanced logging.
ec/src/types.rs Extended Message struct with optional election_id; added new constructor and tests.
voter/src/election.rs Extended Message struct with optional election_id; added new constructor.
voter/src/main.rs Updated message creation to use timestamp-based IDs and the new new_with_election constructor.

Sequence Diagram(s)

sequenceDiagram
    participant Voter
    participant EC
    participant NostrRelay

    Voter->>NostrRelay: Publish Gift Wrap (kind 1) token request (with election_id)
    NostrRelay->>EC: Deliver encrypted token request
    EC->>NostrRelay: Publish Gift Wrap response (with election_id)
    NostrRelay->>Voter: Deliver encrypted response

    Voter->>NostrRelay: Publish Gift Wrap (kind 2) vote submission (with election_id)
    NostrRelay->>EC: Deliver encrypted vote submission
    EC->>NostrRelay: Publish updated results (kind 35001)
    NostrRelay->>Voter: Deliver updated results
Loading

Poem

In burrows deep, the code did grow,
With Nostr’s flow, elections show.
Each vote and token knows its place,
No cross-burrow, no misplaced trace.
A hop, a skip, a protocol new—
Criptocracia’s vision comes into view!
🐇✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Clippy (1.86.0)
Updating crates.io index

warning: failed to write cache, path: /usr/local/registry/index/index.crates.io-1949cf8c6b5b557f/.cache/an/yh/anyhow, error: Permission denied (os error 13)
Downloading crates ...
Downloaded allocator-api2 v0.2.21
error: failed to create directory /usr/local/registry/cache/index.crates.io-1949cf8c6b5b557f

Caused by:
Permission denied (os error 13)

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (5)
ec/examples/create_1b3c.rs (1)

1-84: LGTM! Well-structured gRPC example with minor documentation suggestions.

The example demonstrates proper gRPC client usage for election creation and voter registration. The error handling is appropriate and console output is informative.

Consider adding comments to clarify:

  • The purpose of the hardcoded voter pubkey (line 54)
  • That this is intended for testing/demonstration purposes
  • The short timing values (10 seconds start, 10 minutes duration) are for quick testing
1+/// Example: Create election for mobile app testing
2+/// 
3+/// This example creates a test election with:
4+/// - 10 second start delay for immediate testing
5+/// - 10 minute duration for quick validation
6+/// - Hardcoded test voter pubkey for mobile app testing
 /// Create election for mobile app
ec/examples/debug_1b3c.rs (2)

33-34: Improve timestamp error handling to avoid silent failures.

Using unwrap_or_default() will display the Unix epoch (1970-01-01) if timestamp conversion fails, which could be misleading. Consider explicit error handling or displaying "Invalid timestamp" instead.

-                    println!("   Start: {}", chrono::DateTime::<chrono::Utc>::from_timestamp(election.start_time as i64, 0).unwrap_or_default());
-                    println!("   End: {}", chrono::DateTime::<chrono::Utc>::from_timestamp(election.end_time as i64, 0).unwrap_or_default());
+                    println!("   Start: {}", chrono::DateTime::<chrono::Utc>::from_timestamp(election.start_time as i64, 0)
+                        .map(|dt| dt.to_string())
+                        .unwrap_or_else(|| "Invalid timestamp".to_string()));
+                    println!("   End: {}", chrono::DateTime::<chrono::Utc>::from_timestamp(election.end_time as i64, 0)
+                        .map(|dt| dt.to_string())
+                        .unwrap_or_else(|| "Invalid timestamp".to_string()));

21-22: Consider making hardcoded values configurable for better reusability.

The script contains several hardcoded values (election ID "1b3c", voter public key) that limit its flexibility. Consider accepting these as command-line arguments to make the debug tool more versatile.

Add command-line argument parsing at the beginning of the file:

use clap::Parser;

#[derive(Parser, Debug)]
#[command(about = "Debug tool for checking election voters")]
struct Args {
    /// Election ID to debug
    #[arg(short, long, default_value = "1b3c")]
    election_id: String,
    
    /// Expected voter public key (optional)
    #[arg(short, long)]
    voter_pubkey: Option<String>,
    
    /// Admin service address
    #[arg(short, long, default_value = "http://127.0.0.1:50001")]
    admin_addr: String,
}

Then update the main function to use these arguments instead of hardcoded values.

Also applies to: 65-65, 73-75

ec/src/main.rs (1)

313-374: Well-implemented election-specific token request handling with backward compatibility.

The code correctly implements the new election-specific protocol while maintaining backward compatibility for legacy clients. The logging clearly distinguishes between the two protocols.

Consider extracting the token request cloning into a helper method to reduce code duplication:

fn clone_token_request(req: &BlindTokenRequest) -> BlindTokenRequest {
    BlindTokenRequest {
        voter_pk: req.voter_pk.clone(),
        blinded_h_n: req.blinded_h_n.clone(),
    }
}
NOSTR.md (1)

149-156: Fix inconsistent list formatting for better readability.

The document uses both asterisks and dashes for unordered lists. For consistency, all lists should use dashes as per the markdown style guide.

Replace all asterisk bullets with dashes:

-* **Blinded hash nonce**: `blind(SHA256(random_nonce))` encoded in Base64
-* **Encryption**: The entire message is wrapped in NIP-59 Gift Wrap using voter's keys
+- **Blinded hash nonce**: `blind(SHA256(random_nonce))` encoded in Base64
+- **Encryption**: The entire message is wrapped in NIP-59 Gift Wrap using voter's keys

Apply this change to all lines mentioned in the range (149-156, 164-166, 170-172, 176-177, 181-183, 236-238).

Also applies to: 164-166, 170-172, 176-177, 181-183, 236-238

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a4bf7a and cd9136f.

📒 Files selected for processing (9)
  • NOSTR.md (1 hunks)
  • README.md (1 hunks)
  • ec/examples/create_1b3c.rs (1 hunks)
  • ec/examples/debug_1b3c.rs (1 hunks)
  • ec/src/election.rs (2 hunks)
  • ec/src/main.rs (2 hunks)
  • ec/src/types.rs (2 hunks)
  • voter/src/election.rs (1 hunks)
  • voter/src/main.rs (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
ec/examples/create_1b3c.rs (2)
ec/examples/debug_1b3c.rs (1)
  • main (14-88)
ec/src/main.rs (1)
  • main (103-619)
voter/src/election.rs (2)
ec/src/types.rs (3)
  • new (11-13)
  • new (33-35)
  • new_with_election (37-39)
ec/src/election.rs (1)
  • new (48-74)
🪛 LanguageTool
NOSTR.md

[uncategorized] ~14-~14: Possible missing comma found.
Context: ... event publishing. ## Election Events (Kind 35000) ### Event Type Election announc...

(AI_HYDRA_LEO_MISSING_COMMA)

🪛 markdownlint-cli2 (0.17.2)
NOSTR.md

149-149: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


150-150: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


154-154: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


155-155: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


156-156: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


164-164: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


165-165: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


166-166: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


170-170: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


171-171: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


172-172: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


176-176: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


177-177: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


181-181: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


182-182: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


183-183: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


236-236: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


237-237: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)


238-238: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)

🔇 Additional comments (13)
voter/src/election.rs (1)

96-107: LGTM! Well-designed election isolation enhancement.

The addition of the optional election_id field with proper documentation and dual constructors maintains backward compatibility while enabling election-specific validation. The implementation correctly follows Rust patterns and supports the PR's election isolation security objective.

voter/src/main.rs (2)

472-477: LGTM! Proper election-specific message construction.

The implementation correctly uses the new new_with_election constructor with timestamp-based unique IDs and proper election context. This enhances election isolation security as intended.


546-551: LGTM! Consistent vote message construction.

The vote message construction follows the same secure pattern as token requests, ensuring proper election isolation and unique message identification.

README.md (1)

134-143: LGTM! Improved documentation structure and clarity.

The enhanced Nostr Integration section provides better organization and clarity about the protocol's role in election announcements, results, and encrypted communication. The reference to NOSTR.md is helpful for detailed technical specifications.

ec/src/types.rs (2)

28-39: LGTM! Consistent Message struct implementation.

The changes mirror those in the voter codebase, ensuring consistency across the system. The dual constructor approach maintains backward compatibility while enabling election-specific validation.


69-81: LGTM! Excellent test coverage for new functionality.

The test suite properly verifies both the original constructor behavior (election_id = None) and the new election-specific constructor, including JSON serialization/deserialization roundtrip testing.

ec/src/election.rs (5)

16-16: LGTM!

Adding Clone to BlindTokenRequest is appropriate as all its fields are clonable, and it's needed for the new test cases.


787-838: Well-structured test for token issuance isolation.

This test effectively verifies that tokens can only be issued for elections where the voter is registered, preventing cross-election token issuance attacks.


841-913: Good test demonstrating the need for election_id validation.

The test correctly shows that token isolation at the election level isn't sufficient without protocol-level validation. The comment at lines 902-903 accurately explains that the real protection comes from the election_id validation in main.rs.


916-975: Comprehensive test for used token isolation.

This test properly validates that each election maintains an independent set of used tokens, allowing the same h_n value to be used across different elections without conflicts.


978-1046: Excellent test coverage for voter authorization isolation.

This test thoroughly validates that voter registration and authorization are properly isolated between elections, ensuring voters can only obtain tokens for elections where they're registered.

ec/src/main.rs (1)

452-523: Robust vote submission handling with election isolation.

The implementation correctly handles election-specific vote submissions while maintaining backward compatibility. The database persistence of used tokens and comprehensive error logging enhance the system's reliability.

NOSTR.md (1)

1-368: Excellent technical documentation for Nostr protocol integration.

This comprehensive document effectively explains the Nostr integration, covering all aspects from election announcements to vote submissions with clear examples and security considerations. The flow diagrams and code references are particularly helpful.

@grunch grunch merged commit be1bf66 into main Jul 7, 2025
1 check passed
@grunch grunch deleted the fix-election-isolation-security branch July 7, 2025 21:11
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