agentsclimarketplace

Code security

Skill jjmendezrodriguez/jm-claude-plugin/skills/code-security

Security best practices for TypeScript, React, and Supabase applications. Use this when handling user input, managing secrets, implementing auth with Supabase, configuring RLS policies, validating with Zod, or reviewing code for XSS/injection vulnerabilities. Trigger on: any auth flow, form input, environment variables, API endpoint, or database query. Apply proactively — security is not optional.From its SKILL.md

Install
npx -y skills add jjmendezrodriguez/jm-claude-plugin --skill code-security

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

4.7 KB, as published. Nobody here has run it

Security — TS / React / Supabase

Staff Engineer standard: security is a design constraint, not a feature.


1. Security Flow (every critical operation)

1. AUTHENTICATE  → Verify identity (Supabase Auth)
2. AUTHORIZE     → Check permissions (RLS policies)
3. VALIDATE      → Validate inputs (Zod schemas)
4. PROCESS       → Execute business logic
5. LOG           → Record action (NO sensitive data)

2. Input Validation with Zod

import { z } from "zod";

// ✅ Validate ALL external input at system boundaries
const updateProfileSchema = z.object({
  name: z.string().min(2).max(100).trim(),
  email: z.string().email(),
  bio: z.string().max(500).optional(),
});

// In Edge Function / API handler
const result = updateProfileSchema.safeParse(req.body);
if (!result.success) {
  return new Response(JSON.stringify({
    type: "ValidationError",
    errors: result.error.issues.map((i) => i.message),
  }), { status: 400 });
}
// result.data is now typed and sanitized

What to validate:

✅ VALIDATE:                    ❌ NEVER TRUST:
- Type (string, number)         - User input (forms, params)
- Length (min, max)              - URL parameters
- Format (email, UUID)          - Headers (except from proxy)
- Range (min/max value)         - File uploads
- Whitelist (allowed values)    - External API responses

3. Secrets Management

// ❌ NEVER — hardcoded secrets
const SUPABASE_KEY = "eyJhbGci...";

// ✅ ALWAYS — environment variables
const SUPABASE_KEY = import.meta.env.VITE_SUPABASE_ANON_KEY;

// ✅ Server-side (Edge Functions) — no VITE_ prefix
const SERVICE_KEY = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY");

Rules:

  • VITE_ prefix = exposed to browser (anon key only)
  • Service role key = server-side only (Edge Functions)
  • .env in .gitignore — always
  • .env.example committed with placeholder values

4. Supabase RLS (Row Level Security)

-- ✅ Users can only read their own data
CREATE POLICY "users_read_own" ON profiles
  FOR SELECT USING (auth.uid() = user_id);

-- ✅ Users can only update their own data
CREATE POLICY "users_update_own" ON profiles
  FOR UPDATE USING (auth.uid() = user_id)
  WITH CHECK (auth.uid() = user_id);

-- ❌ BAD — Anyone can read everything
CREATE POLICY "public_read" ON profiles
  FOR SELECT USING (true);

RLS checklist:

[ ] RLS enabled on EVERY table with user data
[ ] SELECT policies restrict to own data (unless public)
[ ] INSERT policies validate user_id = auth.uid()
[ ] UPDATE policies use both USING and WITH CHECK
[ ] DELETE policies are restrictive (soft-delete preferred)
[ ] Service role key NEVER used in frontend

5. React XSS Prevention

Never render raw HTML from user input. React auto-escapes JSX expressions ({variable}), which is safe by default.

Avoid setting innerHTML directly. If you must render HTML from a trusted source (e.g., a CMS), always sanitize it first with a library like DOMPurify.

Rules:

  • Never interpolate user input into href, src, or style attributes
  • Validate URLs with new URL(input) + whitelist allowed protocols
  • Use CSP (Content Security Policy) headers as an extra layer

6. Auth Patterns (Supabase)

// ✅ Protect routes — check session before rendering
const ProtectedRoute = ({ children }: { children: ReactNode }) => {
  const { session, isLoading } = useAuth();

  if (isLoading) return <Spinner />;
  if (!session) return <Navigate to="/login" replace />;

  return children;
};

// ✅ Edge Function — verify JWT server-side
const { data: { user }, error } = await supabase.auth.getUser(
  req.headers.get("Authorization")?.replace("Bearer ", "") ?? ""
);
if (error || !user) return new Response("Unauthorized", { status: 401 });

7. Security Checklist (before every PR)

[ ] No hardcoded secrets (grep for API keys, tokens)
[ ] Zod validates all external input
[ ] RLS policies cover all tables with user data
[ ] No raw HTML rendering without sanitization
[ ] Service role key not exposed to frontend
[ ] .env in .gitignore, .env.example committed
[ ] Auth checked before data access
[ ] No sensitive data in error messages or logs
[ ] CORS properly configured (Supabase dashboard)

Keep looking

Skills are one crate of 626,474. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.