Back to skill

Security audit

nextjs-pro

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Next.js helper, but some included examples teach unsafe server-side mutation and API patterns that users should review before installation.

Review this skill before installing if you expect agents to implement production Next.js server actions or route handlers. The package is not executing code or collecting data, but its examples should be treated as simplified and corrected with explicit server-side authentication, authorization, schema validation, and allowlisted fields.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
references/examples.md:72
Finding

Server Action Allows User Modification Without Server-Side Authorization

Content
View full analysis

Vulnerability Details

File Location: references/examples.md, lines 72–102
Vulnerability Type: Insecure direct object reference and missing function-level authorization
Risk Level: High

Vulnerable Code

tsx
export async function updateUser(userId: string, formData: FormData) {
  const validatedFields = UpdateUserSchema.safeParse({
    name: formData.get('name'),
    email: formData.get('email'),
  });

  if (!validatedFields.success) {
    return {
      errors: validatedFields.error.flatten().fieldErrors,
    };
  }

  try {
    await db.user.update({
      where: { id: userId },
      data: validatedFields.data,
    });

    revalidatePath('/profile');
    revalidateTag('user');
  } catch (error) {
    return { error: 'Failed to update user' };
  }

  redirect('/profile');
}

// Using Server Action in form
// app/profile/edit/page.tsx
export default function EditProfile({ user }: { user: User }) {
  const updateUserWithId = updateUser.bind(null, user.id);

Technical Analysis

The Server Action accepts a userId and uses it directly as the database update selector. Although the submitted fields are schema-validated, the action does not authenticate the caller or verify that the authenticated principal owns the specified account. Input validation does not replace authorization.

Binding the identifier when rendering the form is not, by itself, an authorization control. Server Actions are remotely reachable server endpoints, and access control must be enforced inside the action. If an attacker can invoke the action with a different identifier, or if an untrusted value reaches the bound argument, the database operation will update the selected user without an ownership or role check.

Attack Path

  1. An attacker authenticates as an ordinary user or otherwise obtains access to the exposed Server Action.
  2. The attacker identifies the action endpoint and ...[truncated 880 chars]
Remediation
View remediation

Remediation Suggestions

  • Authenticate inside the Server Action using a trusted server-side session.
  • Derive the target user ID from the verified session for self-service profile updates rather than accepting it as an action argument.
  • If administrators may update other accounts, perform an explicit role and permission check before the database operation.
  • Reject unauthenticated requests and unauthorized target-user combinations before processing form data.
  • Retain strict schema validation and normalize sensitive fields such as email addresses.
  • Require appropriate re-verification before changing security-sensitive identity attributes.
  • Record security audit events for profile and email changes without logging sensitive form data.

A safer design is:

tsx
export async function updateCurrentUser(formData: FormData) {
  const session = await getServerSession(authConfig);

  if (!session?.user?.id) {
    throw new Error('Unauthorized');
  }

  const validatedFields = UpdateUserSchema.safeParse({
    name: formData.get('name'),
    email: formData.get('email'),
  });

  if (!validatedFields.success) {
    return {
      errors: validatedFields.error.flatten().fieldErrors,
    };
  }

  await db.user.update({
    where: { id: session.user.id },
    data: validatedFields.data,
  });

  revalidatePath('/profile');
}

T09 · Insecure Skill Coding Practices

Warning
Location
references/examples.md:198
Finding

Route Handler Passes Unvalidated JSON Directly to Business Logic

Content
View full analysis

Vulnerability Details

File Location: references/examples.md, lines 198–208
Vulnerability Type: Missing request validation and potential mass assignment
Risk Level: Medium

Vulnerable Code

tsx
export async function POST(request: NextRequest) {
  const body = await request.json();
  
  const { data, error } = await createPost(body);
  
  if (error) {
    return NextResponse.json({ error }, { status: 400 });
  }
  
  return NextResponse.json(data, { status: 201 });
}

Technical Analysis

The route parses arbitrary JSON and forwards the complete object directly to createPost. The handler does not apply a schema, allowlist permitted properties, enforce semantic constraints, or demonstrate authentication and authorization. It also does not show a request-size limit.

If createPost passes properties into a database or object-relational mapper, an attacker may supply fields that normal clients are not intended to control, such as ownership, publication state, administrative flags, or internal identifiers. This creates a potential mass-assignment condition. Malformed or excessively large request bodies could also trigger unexpected behavior or resource consumption.

The implementation of createPost is not present, so a specific downstream injection or privilege escalation cannot be confirmed. The confirmed weakness is unsafe handling at the route's trust boundary.

Attack Path

  1. An attacker sends a crafted JSON request to the post-creation endpoint.
  2. The body includes unexpected properties, invalid values, or an excessively large payload.
  3. The route parses the JSON without schema validation or property allowlisting.
  4. The complete attacker-controlled object is passed to createPost.
  5. If downstream logic accepts those properties, unauthorized fields may be persisted or business rules may be bypassed.

Impact Assessment

Potential impact includes unauthorized ...[truncated 337 chars]

Remediation
View remediation

Remediation Suggestions

  • Validate request bodies with a strict schema before invoking business logic.
  • Reject unknown properties and apply explicit length, format, and value constraints.
  • Construct a new object containing only permitted fields instead of forwarding the original body.
  • Authenticate the caller and verify permission to create the resource.
  • Derive ownership and privileged attributes from the verified server-side identity, not request JSON.
  • Enforce request-body size limits at the application or reverse-proxy layer.
  • Return generic client-facing errors while logging appropriate diagnostic details securely.
  • Repeat critical validation and authorization in the service layer to provide defense in depth.

For example:

tsx
const CreatePostSchema = z.object({
  title: z.string().min(1).max(200),
  content: z.string().min(1).max(50_000),
}).strict();

export async function POST(request: NextRequest) {
  const session = await getServerSession(authConfig);

  if (!session?.user?.id) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  const parsed = CreatePostSchema.safeParse(await request.json());

  if (!parsed.success) {
    return NextResponse.json(
      { error: 'Invalid request body' },
      { status: 400 }
    );
  }

  const result = await createPost({
    title: parsed.data.title,
    content: parsed.data.content,
    authorId: session.user.id,
  });

  return NextResponse.json(result, { status: 201 });
}
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (1)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill description is broad enough that it may be invoked for a wide range of Next.js or React-related tasks without clear boundaries. Overly broad routing can cause the agent to apply this skill in inappropriate contexts, increasing the chance of irrelevant guidance, missed security considerations from more specialized skills, or unintended priority over better-matched instructions.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.