llm-public-opinion-analytics-assistant
llm public opinion analytics assistant
vibe-security-skill
Agent skill that audits vibe-coded apps for common security vulnerabilities introduced by AI coding assistants
Full skill instructions
Skill by ara.so — Security Skills collection.
This skill provides expertise in using the Vibe Security tool to audit vibe-coded applications for common security vulnerabilities that AI coding assistants frequently introduce. It helps identify hardcoded secrets, missing RLS policies, insecure auth patterns, payment vulnerabilities, and other security anti-patterns.
Vibe Security is an agent skill that scans codebases for security vulnerability patterns common in AI-generated code. It uses technology-specific reference files to audit only relevant parts of your stack (Supabase, Stripe, React Native, etc.), catching issues like:
npx skills add https://github.com/raroque/vibe-security-skill --skill vibe-security
npx skills add https://github.com/raroque/vibe-security-skill --skill vibe-security
Select "Codex" when prompted.
# Project-level
git clone https://github.com/raroque/vibe-security-skill.git
cp -r vibe-security-skill/vibe-security/ .claude/skills/vibe-security/
# Global installation
cp -r vibe-security-skill/vibe-security/ ~/.claude/skills/vibe-security/
Claude Code:
/vibe-security
Or use natural language:
Codex:
$vibe-security
The skill automatically activates when working with:
Bad Pattern:
// ❌ Hardcoded secret
const supabase = createClient(
'https://xxx.supabase.co',
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
)
// ❌ Exposed in client bundle
const OPENAI_API_KEY = 'sk-proj-...'
Good Pattern:
// ✅ Environment variable
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
// ✅ Server-side only
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY // Not NEXT_PUBLIC_
})
Bad Pattern:
-- ❌ RLS disabled
CREATE TABLE user_data (
id uuid,
user_id uuid,
sensitive_data text
);
-- No ALTER TABLE ... ENABLE ROW LEVEL SECURITY
-- ❌ Allows everything
CREATE POLICY "allow_all" ON user_data
FOR ALL USING (true);
Good Pattern:
-- ✅ RLS enabled with proper policies
CREATE TABLE user_data (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
user_id uuid REFERENCES auth.users NOT NULL,
sensitive_data text
);
ALTER TABLE user_data ENABLE ROW LEVEL SECURITY;
CREATE POLICY "users_select_own" ON user_data
FOR SELECT USING (auth.uid() = user_id);
CREATE POLICY "users_insert_own" ON user_data
FOR INSERT WITH CHECK (auth.uid() = user_id);
CREATE POLICY "users_update_own" ON user_data
FOR UPDATE USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
Bad Pattern:
// ❌ Decoding without verification
import jwt from 'jsonwebtoken'
const decoded = jwt.decode(token) // No signature check!
const userId = decoded.sub
// ❌ Middleware-only auth
// middleware.ts
export function middleware(req: NextRequest) {
const token = req.cookies.get('token')
if (!token) return NextResponse.redirect('/login')
}
// app/api/sensitive/route.ts - NOT protected!
export async function GET() {
return NextResponse.json(await db.getAllUserData())
}
Good Pattern:
// ✅ Verify JWT signature
import jwt from 'jsonwebtoken'
const decoded = jwt.verify(token, process.env.JWT_SECRET!) as JwtPayload
const userId = decoded.sub
// ✅ Auth in every API route
// lib/auth.ts
export async function requireAuth(req: Request) {
const token = req.headers.get('authorization')?.replace('Bearer ', '')
if (!token) throw new Error('Unauthorized')
const decoded = jwt.verify(token, process.env.JWT_SECRET!)
return decoded
}
// app/api/sensitive/route.ts
export async function GET(req: Request) {
const user = await requireAuth(req)
return NextResponse.json(await db.getUserData(user.sub))
}
Bad Pattern:
// ❌ Client submits price
export async function POST(req: Request) {
const { amount, productId } = await req.json()
const session = await stripe.checkout.sessions.create({
line_items: [{
price_data: {
currency: 'usd',
product: productId,
unit_amount: amount // ❌ Trusting client!
},
quantity: 1
}],
mode: 'payment'
})
}
Good Pattern:
// ✅ Server determines price
const PRICES = {
'basic': 999,
'pro': 2999,
'enterprise': 9999
} as const
export async function POST(req: Request) {
const { plan } = await req.json()
if (!PRICES[plan]) throw new Error('Invalid plan')
const session = await stripe.checkout.sessions.create({
line_items: [{
price_data: {
currency: 'usd',
product: plan,
unit_amount: PRICES[plan] // ✅ Server-controlled
},
quantity: 1
}],
mode: 'payment'
})
}
// ✅ Verify webhook signatures
export async function POST(req: Request) {
const body = await req.text()
const sig = req.headers.get('stripe-signature')!
const event = stripe.webhooks.constructEvent(
body,
sig,
process.env.STRIPE_WEBHOOK_SECRET!
)
// Process event...
}
Bad Pattern:
// ❌ No rate limiting on expensive endpoints
export async function POST(req: Request) {
const { prompt } = await req.json()
const completion = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: prompt }]
})
return NextResponse.json(completion)
}
Good Pattern:
// ✅ Server-side rate limiting
import { Ratelimit } from '@upstash/ratelimit'
import { Redis } from '@upstash/redis'
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, '1 h'),
analytics: true
})
export async function POST(req: Request) {
const user = await requireAuth(req)
const { success } = await ratelimit.limit(user.sub)
if (!success) {
return NextResponse.json(
{ error: 'Rate limit exceeded' },
{ status: 429 }
)
}
const { prompt } = await req.json()
const completion = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: prompt }],
max_tokens: 1000 // ✅ Cap token usage
})
return NextResponse.json(completion)
}
Bad Pattern:
// ❌ API key in JS bundle
const OPENAI_API_KEY = 'sk-proj-...'
// ❌ Token in AsyncStorage
import AsyncStorage from '@react-native-async-storage/async-storage'
await AsyncStorage.setItem('auth_token', token)
Good Pattern:
// ✅ Use backend proxy for AI calls
const response = await fetch('https://api.myapp.com/ai/chat', {
method: 'POST',
headers: {
'Authorization': `Bearer ${userToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ prompt })
})
// ✅ Use secure storage for tokens
import * as SecureStore from 'expo-secure-store'
await SecureStore.setItemAsync('auth_token', token)
const token = await SecureStore.getItemAsync('auth_token')
Bad Pattern:
// ❌ SQL injection vulnerability
export async function GET(req: Request) {
const { searchParams } = new URL(req.url)
const userId = searchParams.get('userId')
const result = await db.$queryRawUnsafe(
`SELECT * FROM users WHERE id = ${userId}`
)
}
// ❌ Prisma operator injection
const users = await prisma.user.findMany({
where: req.query // ❌ Direct user input
})
Good Pattern:
// ✅ Parameterized queries
export async function GET(req: Request) {
const { searchParams } = new URL(req.url)
const userId = searchParams.get('userId')
const result = await db.$queryRaw`
SELECT * FROM users WHERE id = ${userId}
`
}
// ✅ Validate and sanitize input
const userIdSchema = z.string().uuid()
const userId = userIdSchema.parse(searchParams.get('userId'))
const user = await prisma.user.findUnique({
where: { id: userId }
})
Vibe Security uses reference files organized by technology. The skill automatically detects your stack and applies relevant checks.
You can extend the skill by adding custom security rules in your project's .claude/skills/vibe-security/rules/ directory.
Make sure you're working with code that involves:
Or explicitly trigger with /vibe-security (Claude) or $vibe-security (Codex).
The skill prioritizes security over convenience. If you have a legitimate use case for a flagged pattern:
The skill focuses on common AI-generated security mistakes. For comprehensive security:
# .env.local (never commit)
DATABASE_URL="postgresql://..."
STRIPE_SECRET_KEY="sk_test_..."
OPENAI_API_KEY="sk-proj-..."
# Public vars (safe in client bundle)
NEXT_PUBLIC_SUPABASE_URL="https://xxx.supabase.co"
NEXT_PUBLIC_SUPABASE_ANON_KEY="eyJ..."
// next.config.js
const securityHeaders = [
{
key: 'X-DNS-Prefetch-Control',
value: 'on'
},
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubDomains; preload'
},
{
key: 'X-Frame-Options',
value: 'SAMEORIGIN'
},
{
key: 'X-Content-Type-Options',
value: 'nosniff'
},
{
key: 'Referrer-Policy',
value: 'origin-when-cross-origin'
}
]
module.exports = {
async headers() {
return [
{
source: '/:path*',
headers: securityHeaders
}
]
}
}
import { z } from 'zod'
const createUserSchema = z.object({
email: z.string().email(),
name: z.string().min(1).max(100),
age: z.number().int().min(13).max(120)
})
export async function POST(req: Request) {
const body = await req.json()
const validated = createUserSchema.parse(body)
// Safe to use validated data
await db.user.create({ data: validated })
}
Created by Chris Raroque and the team at Aloa.
llm public opinion analytics assistant
apache airflow orchestration
roblox mm2 analytics toolkit
mm2 analytics roblox tracker
mm2 analytics roblox toolkit
understand anything knowledge graph
mm2 roblox analytics tracker
murder mystery 2 analytics toolkit
mm2 analytics dashboard roblox
mm2 roblox analytics toolkit
agent browser automation
agency agents ai specialists
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience