Skip to content

QR Code Size Parameter Has No Upper Bound — Unauthenticated DoS #226

@Ridanshi

Description

@Ridanshi

Summary

The public QR code generation endpoint accepts arbitrary size values without enforcing any upper bound before generating raster images.

An unauthenticated attacker can supply extremely large dimensions and force excessive memory allocation or event-loop blocking during QR generation.


Affected File

apps/backend/src/routes/public.ts


Root Cause

The route currently parses the requested QR size directly from user input:

const size = parseInt((request.query as any).size || '400', 10);

and passes it directly into the QR generation flow:

const png = await generateQRBuffer(profileUrl, {
  width: size
});

No maximum limit is enforced before passing the value into the QR rendering library.


Security Impact

An attacker can trigger extremely large image allocations using requests such as:

GET /api/u/testuser/qr?size=50000

Large raster generation can:

  • exhaust server memory,
  • block the Node.js event loop,
  • trigger OOM crashes,
  • severely degrade request throughput.

The endpoint:

  • is public,
  • requires no authentication,
  • and currently has no rate limiting.

Reproduction

Send:

GET /api/u/testuser/qr?size=50000

Observe:

  • excessive CPU usage,
  • memory spikes,
  • request stalls,
  • or process instability depending on runtime limits.

Proposed Fix

Add strict upper-bound validation before QR generation.

Suggested approach:

const MAX_QR_SIZE = 2048;

Reject:

  • negative sizes,
  • zero,
  • NaN values,
  • and excessively large dimensions.

Return:

400 Bad Request

for invalid values.

Additional recommendation:

  • apply IP-based rate limiting to public QR routes.

Acceptance Criteria

  • QR size values are validated before image generation.
  • Excessively large dimensions are rejected safely.
  • Invalid numeric inputs return 400 responses.
  • Legitimate QR generation behavior remains unchanged.
  • Endpoint remains stable under malicious requests.

Severity

Medium

This creates an unauthenticated denial-of-service vector against a public endpoint.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions