SE

Provides essential security guidance for securing web applications and API integrations.

Install

mkdir -p .claude/skills/security-review-augustsnow1127 && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/15607" && unzip -o skill.zip -d .claude/skills/security-review-augustsnow1127 && rm skill.zip

Installs to .claude/skills/security-review-augustsnow1127

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Security checklist and best practices for the personal blog project
67 charsno explicit “when” trigger
Intermediate

Key capabilities

  • Check for hardcoded secrets in source code
  • Validate environment variables at runtime
  • Implement rate limiting for API calls
  • Sanitize user input to prevent XSS
  • Configure Content Security Policy (CSP) headers
  • Validate Notion API data before rendering

How it works

The skill provides a checklist and code examples to ensure secure handling of environment variables, API interactions, and user input. It covers prevention of common vulnerabilities like XSS and SQL injection, and guides on configuring security headers.

Inputs & outputs

You give it
Codebase for a Next.js + Notion blog project
You get back
Security checklist, code examples for secure practices, and identified vulnerabilities

When to use security-review

  • Audit env variable usage
  • Secure notion api integration
  • Validate input sanitization
  • Verify security checklist

About this skill

Security Review Checklist

This skill provides a comprehensive security review checklist for the Next.js + Notion blog.

Environment Variables Security

✅ Required Checks

  • No hardcoded secrets in source code
  • All API keys in .env.local file
  • .env.local is in .gitignore
  • Environment variables validated at runtime
  • No secrets in client-side code

Implementation

// lib/env.ts - Environment variable validation
export function validateEnv() {
  const required = ['NOTION_API_KEY', 'NOTION_DATABASE_ID'];
  
  for (const key of required) {
    if (!process.env[key]) {
      throw new Error(`Missing required environment variable: ${key}`);
    }
  }
}

// Call in server-side code only
validateEnv();

❌ Common Mistakes

// ❌ NEVER do this
const API_KEY = 'ntn_abc123...'; // Hardcoded secret

// ❌ NEVER expose in client components
'use client';
const key = process.env.NOTION_API_KEY; // Exposed to browser!

// ✅ CORRECT - Server-side only
// app/api/posts/route.ts
export async function GET() {
  const key = process.env.NOTION_API_KEY; // Safe - server-side
  // ...
}

API Security

Notion API Best Practices

  • Rate limiting - Handle 429 responses
  • Error handling - Don't expose internal errors
  • Input validation - Validate all user inputs
  • CORS configuration - Restrict origins if needed
// lib/notion.ts - Secure API wrapper
export async function getPosts(): Promise<NotionPost[]> {
  try {
    const response = await notion.databases.query({
      database_id: process.env.NOTION_DATABASE_ID!,
      filter: {
        property: 'Published',
        checkbox: { equals: true },
      },
    });
    
    return response.results.map(mapNotionToPost);
  } catch (error) {
    // ✅ Log error server-side
    console.error('Notion API error:', error);
    
    // ❌ Don't expose internal error details
    // throw error;
    
    // ✅ Return safe fallback
    return [];
  }
}

Rate Limiting

// lib/rateLimit.ts
const RATE_LIMIT = 3; // requests per second
const cache = new Map<string, number[]>();

export function rateLimit(identifier: string): boolean {
  const now = Date.now();
  const timestamps = cache.get(identifier) || [];
  
  // Remove timestamps older than 1 second
  const recent = timestamps.filter(t => now - t < 1000);
  
  if (recent.length >= RATE_LIMIT) {
    return false; // Rate limit exceeded
  }
  
  recent.push(now);
  cache.set(identifier, recent);
  return true;
}

XSS Prevention

Content Sanitization

  • Sanitize user input (if accepting comments/forms)
  • Escape HTML in dynamic content
  • Use React's built-in escaping (automatic)
  • Validate Notion content before rendering
// components/NotionRenderer.tsx
export function NotionRenderer({ blocks }: { blocks: NotionBlock[] }) {
  return blocks.map(block => {
    switch (block.type) {
      case 'paragraph':
        // ✅ React automatically escapes text
        return <p>{block.paragraph.rich_text[0]?.plain_text}</p>;
      
      case 'code':
        // ✅ Use proper code highlighting library
        return <SyntaxHighlighter>{block.code.rich_text[0]?.plain_text}</SyntaxHighlighter>;
      
      default:
        return null;
    }
  });
}

❌ Dangerous Patterns

// ❌ NEVER use dangerouslySetInnerHTML with unsanitized content
<div dangerouslySetInnerHTML={{ __html: userInput }} />

// ✅ If you must use it, sanitize first
import DOMPurify from 'isomorphic-dompurify';

<div dangerouslySetInnerHTML={{ 
  __html: DOMPurify.sanitize(content) 
}} />

CSRF Protection

Next.js provides built-in CSRF protection for Server Actions.

// app/actions.ts
'use server';

export async function submitForm(formData: FormData) {
  // ✅ Automatically protected by Next.js
  const email = formData.get('email');
  // Process form...
}

SQL Injection Prevention

Not applicable for this project (using Notion API), but if adding a database:

// ✅ Use parameterized queries
const result = await db.query(
  'SELECT * FROM posts WHERE slug = $1',
  [slug]
);

// ❌ NEVER concatenate user input
const result = await db.query(
  `SELECT * FROM posts WHERE slug = '${slug}'` // VULNERABLE!
);

Authentication & Authorization

Currently not implemented, but if adding:

Checklist

  • Use established auth library (NextAuth.js, Clerk, etc.)
  • Implement HTTPS only
  • Use secure session cookies
  • Implement proper password hashing (bcrypt, Argon2)
  • Add rate limiting to login endpoints
  • Implement CSRF tokens
  • Use secure password reset flow

Content Security Policy (CSP)

// next.config.ts
const nextConfig = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'Content-Security-Policy',
            value: [
              "default-src 'self'",
              "script-src 'self' 'unsafe-eval' 'unsafe-inline'",
              "style-src 'self' 'unsafe-inline'",
              "img-src 'self' data: https:",
              "font-src 'self' data:",
              "connect-src 'self' https://api.notion.com",
            ].join('; '),
          },
          {
            key: 'X-Frame-Options',
            value: 'DENY',
          },
          {
            key: 'X-Content-Type-Options',
            value: 'nosniff',
          },
          {
            key: 'Referrer-Policy',
            value: 'strict-origin-when-cross-origin',
          },
        ],
      },
    ];
  },
};

Dependency Security

Regular Audits

# Check for vulnerabilities
npm audit

# Fix automatically
npm audit fix

# Check for outdated packages
npm outdated

Dependabot Configuration

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 10

Vercel Deployment Security

Environment Variables

  • Set environment variables in Vercel dashboard
  • Use different keys for preview/production
  • Enable "Encrypted" option for sensitive vars

Security Headers

  • Enable HTTPS only
  • Configure security headers in next.config.ts
  • Set up custom domain with SSL

Notion Integration Security

API Key Management

  • Use integration token (not personal token)
  • Limit integration permissions to minimum required
  • Rotate keys periodically
  • Monitor API usage

Data Validation

// lib/notion.ts - Validate Notion data
function mapNotionToPost(page: any): NotionPost {
  // ✅ Validate required fields
  if (!page.properties.Title?.title?.[0]?.plain_text) {
    throw new Error('Invalid post: missing title');
  }
  
  if (!page.properties.Slug?.rich_text?.[0]?.plain_text) {
    throw new Error('Invalid post: missing slug');
  }
  
  return {
    id: page.id,
    title: page.properties.Title.title[0].plain_text,
    slug: page.properties.Slug.rich_text[0].plain_text,
    // ... other fields
  };
}

Security Review Workflow

Before Every Deployment

  • Run npm audit
  • Check .env.local not committed
  • Review new dependencies
  • Test error handling
  • Verify environment variables in Vercel
  • Check security headers
  • Review Notion API permissions

Monthly Security Tasks

  • Update dependencies
  • Rotate API keys
  • Review access logs
  • Check for new vulnerabilities
  • Update security policies

Incident Response Plan

If a security issue is discovered:

  1. Assess Impact - Determine scope and severity
  2. Contain - Rotate compromised keys immediately
  3. Investigate - Review logs and access patterns
  4. Fix - Deploy security patch
  5. Notify - Inform affected users if necessary
  6. Document - Record incident and response

Security Resources

How it compares

This skill offers a project-specific security checklist and implementation guidance for a Next.js + Notion blog, providing concrete code examples for common security practices rather than general security advice.

Compared to similar skills

security-review side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
security-review (this skill)06moReviewIntermediate
middleware-protection16moReviewIntermediate
vercel-data-handling11moNo flagsIntermediate
Server Actions and Auth Guard Order01moNo flagsIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

middleware-protection

dadbodgeoff

Protect routes with Next.js middleware. Check authentication once, protect routes declaratively. Supports public routes, protected routes, and role-based access.

13

vercel-data-handling

jeremylongshore

Implement Vercel PII handling, data retention, and GDPR/CCPA compliance patterns. Use when handling sensitive data, implementing data redaction, configuring retention policies, or ensuring compliance with privacy regulations for Vercel integrations. Trigger with phrases like "vercel data", "vercel PII", "vercel GDPR", "vercel data retention", "vercel privacy", "vercel CCPA".

13

Server Actions and Auth Guard Order

bytetalent

Zod validation before data touch, auth guard sequence, authz inside the action, security headers.

00

reviewing-nextjs-16-patterns

djankies

Review code for Next.js 16 compliance - security patterns, caching, breaking changes. Use when reviewing Next.js code, preparing for migration, or auditing for violations.

11106

firebase

davila7

Firebase gives you a complete backend in minutes - auth, database, storage, functions, hosting. But the ease of setup hides real complexity. Security rules are your last line of defense, and they're often wrong. Firestore queries are limited, and you learn this after you've designed your data model. This skill covers Firebase Authentication, Firestore, Realtime Database, Cloud Functions, Cloud Storage, and Firebase Hosting. Key insight: Firebase is optimized for read-heavy, denormalized data. I

2050

auth-patterns

davepoon

This skill should be used when the user asks about "authentication in Next.js", "NextAuth", "Auth.js", "middleware auth", "protected routes", "session management", "JWT", "login flow", or needs guidance on implementing authentication and authorization in Next.js applications.

720

Search skills

Search the agent skills registry