Skip to content

[P0] Security: Fix IDOR in updateWorldTitle or similar functions #25

Description

@Pamacea

[P0] Security: Audit and Fix IDOR vulnerabilities in update functions

Severity

  • Priority: P0
  • Type: Security (IDOR)
  • Estimation: 4 hours

Problem

Insecure Direct Object Reference (IDOR) vulnerabilities may exist in update functions where ownership verification is missing or incomplete.

Functions to Audit

Known safe (has verifyWorldPermission):

  • updateWorldTitle - ✅ Has verifyWorldPermission(id, user.id)

Needs verification:

  • updateWorldState - Check if it verifies ownership
  • updatePin - Check permission verification
  • updateLayer - Check permission verification
  • updateLoreEntry - Check permission verification
  • updateCharacter - Check permission verification
  • updateGalleryItem - Check permission verification

Audit Checklist

For each update function, verify:

export async function updateResource(id: string, data: any) {
  const user = await getAuthenticatedUser();
  
  // 1. Must verify ownership BEFORE updating
  const resource = await verifyResourcePermission(id, user.id);
  
  // 2. Must not trust client-provided userId/gameWorldId
  if (data.userId !== undefined && data.userId !== user.id) {
    throw new AuthorizationError("Cannot modify userId");
  }
  
  // 3. Update
  const updated = await prisma.resource.update({
    where: { id },
    data: sanitizedData,
  });
  
  return updated;
}

Common IDOR Patterns to Fix

Pattern 1: Missing ownership check

// BAD
export async function updateThing(id: string, data: any) {
  await getAuthenticatedUser(); // Only auth, no ownership!
  return prisma.thing.update({ where: { id }, data });
}

// GOOD
export async function updateThing(id: string, data: any) {
  const user = await getAuthenticatedUser();
  await verifyThingPermission(id, user.id); // Ownership check
  return prisma.thing.update({ where: { id }, data });
}

Pattern 2: Trusting client-provided IDs

// BAD
const updated = await prisma.character.update({
  where: { id: data.id },
  data: { ...data } // Client could provide userId!
});

// GOOD
const { userId, gameWorldId, ...safeData } = data;
const updated = await prisma.character.update({
  where: { id },
  data: safeData,
});

Files to Audit

  • src/features/worlds/actions/worlds.ts - All update functions
  • src/features/pins/actions/pins.ts - All update functions
  • src/features/layers/actions/layers.ts - All update functions
  • src/features/lore/actions/lore.ts - All update functions
  • src/features/characters/actions/characters.ts - All update functions
  • src/features/gallery/actions/gallery.ts - All update functions

Steps to Fix

  1. Audit all update functions for ownership verification
  2. Ensure no function trusts client-provided userId/gameWorldId
  3. Add permission helpers if missing
  4. Write tests for IDOR prevention

Acceptance Criteria

  • All update functions verify ownership
  • No function trusts client-provided userId/gameWorldId
  • IDOR tests added for all update functions
  • Security test suite passes

Notes

Use the existing verifyXPermission helpers from @/shared/lib/server-helpers.

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    criticalCritical issue requiring immediate attentionp0Priority: CriticalsecuritySecurity vulnerability or fix

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions