スキル一覧に戻る
keidsondesigner

validate-security

by keidsondesigner

0🍴 0📅 2026年1月16日
GitHubで見るManusで実行

SKILL.md


name: validate-security description: Valida implementações de segurança em Server Actions, verificando autenticação, autorização e validação de dados. Use para revisar segurança antes de merge ou deploy. tools: Read, Grep, Glob

Validate Security Skill

Esta skill valida implementações de segurança seguindo as diretrizes críticas do projeto Bewear.

Quando Usar

  • Revisar Server Actions antes de merge
  • Auditar segurança do código
  • Verificar conformidade com padrões Bewear
  • Identificar vulnerabilidades de segurança

Checklist de Segurança Obrigatório

1. Diretiva "use server"

CRITICAL: TODA Server Action DEVE ter "use server" na primeira linha.

// ✅ CORRETO
"use server";

import { auth } from "@/lib/auth";

// ❌ INCORRETO
import { auth } from "@/lib/auth";

"use server";

2. Verificação de Autenticação

CRITICAL: TODA Server Action DEVE verificar autenticação.

Padrão obrigatório:

const session = await auth.api.getSession({
  headers: await headers(),
});

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

Verificações:

  • auth.api.getSession() chamado
  • headers: await headers() passado
  • Verificação if (!session?.user) presente
  • throw new Error("Unauthorized") em caso de falha

Arquivo de referência: src/actions/add-cart-product/index.ts (linhas 14-20)

3. Validação de Schema

CRITICAL: TODA Server Action que recebe dados DEVE validar com Zod.

// ✅ CORRETO
import { nomeSchema, NomeSchema } from "./schema";

export async function nomeAction(data: NomeSchema) {
  nomeSchema.parse(data);

  const session = await auth.api.getSession({
    headers: await headers(),
  });
}

// ❌ INCORRETO
export async function nomeAction(data: any) {
  const session = await auth.api.getSession({
    headers: await headers(),
  });
}

Verificações:

  • Schema Zod definido em schema.ts
  • Tipo inferido com z.infer<typeof schema>
  • schema.parse(data) chamado antes de outras operações
  • Parâmetro tipado com tipo inferido

4. Validação de Ownership

CRITICAL: Quando recurso pertence a usuário, DEVE validar ownership.

// ✅ CORRETO
const order = await db.query.orderTable.findFirst({
  where: eq(orderTable.id, orderId),
});

if (!order) {
  throw new Error("Order not found");
}

if (order.userId !== session.user.id) {
  throw new Error("Unauthorized");
}

// ❌ INCORRETO
const order = await db.query.orderTable.findFirst({
  where: eq(orderTable.id, orderId),
});

return order;

Verificações:

  • Recurso buscado do banco
  • Verificação de existência (if (!resource))
  • Comparação resource.userId === session.user.id
  • Error apropriado se ownership falhar

Arquivo de referência: src/actions/create-checkout-session-stripe/index.ts (linhas 38-45)

5. SQL Injection Prevention

Drizzle ORM protege contra SQL injection, mas verifique:

// ✅ CORRETO - Usa query builder Drizzle
const product = await db.query.productTable.findFirst({
  where: eq(productTable.id, productId),
});

// ✅ CORRETO - Usa prepared statements Drizzle
await db.insert(productTable).values({
  name: data.name,
});

// ❌ INCORRETO - SQL direto (NUNCA faça isso)
await db.execute(`SELECT * FROM products WHERE id = '${productId}'`);

Verificações:

  • Usa query builder Drizzle
  • Nunca concatena strings SQL
  • Usa operadores Drizzle (eq, and, or, etc.)

6. Environment Variables

Verificar se variáveis sensíveis estão protegidas:

// ✅ CORRETO
if (!process.env.STRIPE_SECRET_KEY) {
  throw new Error("STRIPE_SECRET_KEY is not set");
}

// ❌ INCORRETO
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

Verificações:

  • Chaves sensíveis verificadas antes de uso
  • Não expor chaves secretas no client
  • Prefixo NEXT_PUBLIC_ apenas para valores públicos

7. Error Messages

Não vazar informações sensíveis em erros:

// ✅ CORRETO
if (user.password !== hashedPassword) {
  throw new Error("Invalid credentials");
}

// ❌ INCORRETO - Vaza informação
if (!user) {
  throw new Error("User with email john@example.com not found");
}

Verificações:

  • Mensagens genéricas para autenticação
  • Não expor IDs internos
  • Não expor stack traces para usuários

8. Rate Limiting

Considerar rate limiting para operações sensíveis:

// Operações que precisam rate limiting:
// - Login / Register
// - Password reset
// - Payment operations
// - Expensive queries

9. CSRF Protection

Next.js Server Actions protege automaticamente contra CSRF.

Verificações:

  • Ação é Server Action (não API Route)
  • Chamada vem de formulário ou código client
  • Não desabilitar proteções built-in

10. Data Sanitization

// ✅ CORRETO - Zod valida e sanitiza
const schema = z.object({
  name: z.string().trim().min(1).max(100),
  email: z.string().email().toLowerCase(),
});

// ❌ INCORRETO - Aceita qualquer input
const schema = z.object({
  name: z.string(),
});

Verificações:

  • Strings têm limites de tamanho
  • Emails validados com .email()
  • Números têm min/max apropriados
  • Trim em strings quando necessário

Padrões de Vulnerabilidade Comuns

🚨 IDOR (Insecure Direct Object Reference)

// ❌ VULNERÁVEL
export async function deleteOrder(orderId: string) {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

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

  await db.delete(orderTable).where(eq(orderTable.id, orderId));
}

// ✅ SEGURO
export async function deleteOrder(orderId: string) {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

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

  const order = await db.query.orderTable.findFirst({
    where: eq(orderTable.id, orderId),
  });

  if (!order) {
    throw new Error("Order not found");
  }

  if (order.userId !== session.user.id) {
    throw new Error("Unauthorized");
  }

  await db.delete(orderTable).where(eq(orderTable.id, orderId));
}

🚨 Mass Assignment

// ❌ VULNERÁVEL
export async function updateUser(data: any) {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

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

  await db.update(userTable)
    .set(data)
    .where(eq(userTable.id, session.user.id));
}

// ✅ SEGURO
const updateUserSchema = z.object({
  name: z.string().min(1),
  email: z.string().email(),
});

export async function updateUser(data: UpdateUserSchema) {
  updateUserSchema.parse(data);

  const session = await auth.api.getSession({
    headers: await headers(),
  });

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

  await db.update(userTable)
    .set({
      name: data.name,
      email: data.email,
    })
    .where(eq(userTable.id, session.user.id));
}

🚨 Privilege Escalation

// ❌ VULNERÁVEL
export async function promoteToAdmin(userId: string) {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

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

  await db.update(userTable)
    .set({ role: "admin" })
    .where(eq(userTable.id, userId));
}

// ✅ SEGURO
export async function promoteToAdmin(userId: string) {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

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

  const currentUser = await db.query.userTable.findFirst({
    where: eq(userTable.id, session.user.id),
  });

  if (currentUser?.role !== "admin") {
    throw new Error("Unauthorized - Admin only");
  }

  await db.update(userTable)
    .set({ role: "admin" })
    .where(eq(userTable.id, userId));
}

Processo de Validação

Passo 1: Identificar Server Actions

grep -r '"use server"' src/actions/

Passo 2: Verificar Cada Action

Para cada Server Action encontrada:

  1. Autenticação

    • Tem auth.api.getSession()?
    • Tem headers: await headers()?
    • Tem verificação if (!session?.user)?
  2. Validação

    • Tem schema Zod em schema.ts?
    • Chama schema.parse(data)?
    • Parâmetro tipado corretamente?
  3. Autorização

    • Verifica ownership quando necessário?
    • Compara resource.userId === session.user.id?
    • Verifica roles se necessário?
  4. Database

    • Usa query builder Drizzle?
    • Não tem SQL direto?
    • Usa operadores corretos (eq, and, or)?
  5. Cache

    • Chama revalidatePath() após mutações?
    • Invalida rotas corretas?

Passo 3: Gerar Relatório

## Security Audit Report

### ✅ Server Actions Seguras
- `src/actions/add-cart-product/index.ts` - ✅ Todas verificações passaram
- `src/actions/create-checkout-session-stripe/index.ts` - ✅ Ownership validado

### ⚠️ Server Actions com Alertas
- `src/actions/update-user/index.ts`
  - ⚠️ Falta validação de ownership
  - ⚠️ Schema permite campos sensíveis

### 🚨 Server Actions Vulneráveis
- `src/actions/delete-order/index.ts`
  - 🚨 IDOR: Não verifica ownership
  - 🚨 Qualquer usuário pode deletar qualquer order

### Recomendações
1. Adicionar verificação de ownership em `delete-order`
2. Remover campo `role` do schema em `update-user`
3. Implementar rate limiting em operações de pagamento

Arquivos de Referência

  • Autenticação: src/actions/add-cart-product/index.ts
  • Ownership: src/actions/create-checkout-session-stripe/index.ts
  • Transaction: src/actions/finish-purchase/index.ts
  • Diretrizes: docs/development-guidelines.md (linhas 85-106)

Ferramentas de Auditoria

# Buscar Server Actions sem autenticação
grep -L "auth.api.getSession" src/actions/*/index.ts

# Buscar Server Actions sem validação
grep -L "schema.parse" src/actions/*/index.ts

# Buscar SQL direto (potencialmente inseguro)
grep -r "db.execute" src/

# Buscar concatenação de SQL
grep -r '\${.*}' src/actions/

Checklist Final

Antes de aprovar código:

  • Todas Server Actions têm "use server"
  • Todas verificam autenticação
  • Todas validam com schema Zod
  • Ownership verificado quando necessário
  • Nenhuma SQL injection possível
  • Mensagens de erro não vazam informações
  • Environment variables validadas
  • Cache invalidado após mutações
  • Nenhum IDOR identificado
  • Nenhum mass assignment identificado

スコア

総合スコア

50/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です