Skip to content

Add signature-based integrity verification to QR access-check payloads #244

Description

@Lakes41

Difficulty: Advanced
Type: security

Background
The documented QR payload schema (type, version, guildId, resourceId, optional walletAddress/expiresAt) is plain JSON with format/expiry validation, but no described cryptographic integrity check — anyone who can generate JSON in this shape could produce a QR code the app will accept as a legitimate access-check request.

Problem
Without an integrity/authenticity check, a forged or tampered QR code (e.g., with a manipulated expiresAt to appear not-yet-expired, or a resourceId swapped to something the presenter doesn't actually have rights to trigger) is indistinguishable from a legitimately-issued one at the point of scanning, since access is ultimately re-verified server-side but a malicious payload could still mislead the scanning user or waste access-check calls maliciously.

Expected outcome
QR payloads include a signature field (e.g., an HMAC or ECDSA signature over the canonical payload, issued by the backend/guild admin tooling that generates the QR) that the mobile app verifies locally before even submitting an access check, rejecting unsigned or invalidly-signed payloads with a clear "Untrusted QR code" message — while remaining backward-compatible (or explicitly versioned) with the existing unsigned version: 1 payloads.

Suggested implementation

  • Design a version: 2 payload schema adding a signature field, with a documented canonicalization rule for what exactly gets signed (field order, encoding).
  • Implement local signature verification in src/features/access/ using a public key or shared verification approach appropriate for the signing method chosen (document the key-distribution approach, e.g., embedded public key vs. fetched from the backend on app start, with tradeoffs).
  • Ensure version: 1 (unsigned) payloads either continue to be accepted with a clear "unverified" indicator, or are rejected outright — decide and document the policy explicitly, since this is a meaningful security/compatibility tradeoff.
  • Add a "Signature verified ✓" / "Untrusted QR code" distinct UI state on the scanner screen.
  • Write thorough unit tests: valid signature, tampered payload with a stale signature, missing signature under the new policy, and the version: 1 compatibility decision.
  • Document the new payload version and signing scheme in the README's "QR access check payload" section and in docs/.

Acceptance criteria

  • version: 2 payloads with a valid signature are accepted and clearly marked as verified
  • Tampered payloads (valid signature over different original content) are rejected
  • The version: 1 compatibility policy is explicitly implemented and documented, not left ambiguous
  • README and docs/ updated with the new schema and key-distribution approach

Likely affected files/directories

  • src/features/access/
  • app/access-scanner.tsx
  • docs/
  • README.md

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

GrantFox OSSGrantFox Open Source Sponsorship program tagMaybe RewardedIssue may qualify for a reward upon successful completion per campaign rulesOfficial Campaign | FWC26Official FWC26 campaign issue — eligible for campaign scoring and rewardsadvancedAdvanced difficulty tasks requiring significant domain knowledge and implementation effortsecuritySecurity-related fix, hardening, audit, or vulnerability remediation

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions