Currently, only the latest version of DeesseJS Functions receives security updates.
| Version | Supported |
|---|---|
| Latest (0.x.x) | ✅ |
| Older versions | ❌ |
We strongly recommend keeping your dependencies up to date to ensure you receive security patches.
We take the security of DeesseJS Functions seriously. If you discover a security vulnerability, please follow these guidelines:
Do NOT open a public issue. Instead, send your report privately:
Email: contact@developerssecrets.com
Please include:
- A description of the vulnerability
- Steps to reproduce the issue
- Potential impact of the vulnerability
- Any suggested mitigations or fixes (if known)
- Confirmation: You should receive a response within 48 hours confirming receipt of your report
- Investigation: We will investigate the vulnerability and determine its severity
- Resolution: We will work on a fix and determine a timeline for disclosure
- Disclosure: We will coordinate with you on the public disclosure of the vulnerability
- Critical vulnerabilities: Aim to fix within 7 days
- High severity: Aim to fix within 14 days
- Medium severity: Aim to fix within 30 days
- Low severity: Address in next regular release
Always use Zod schemas to validate and sanitize inputs:
// ✅ Good - Input validation with Zod
const createUser = t.mutation({
args: z.object({
name: z.string().min(2).max(100),
email: z.string().email(),
age: z.number().int().min(0).max(150),
}),
handler: async (ctx, args) => {
// args is validated and type-safe
return success(await ctx.db.users.create(args));
},
});
// ❌ Bad - No input validation
const createUser = t.mutation({
args: z.object({}),
handler: async (ctx, args) => {
// args could contain anything!
return success(await ctx.db.users.create(args));
},
});Never expose sensitive information in the context:
// ❌ Bad - Exposing secrets in context
const { t } = defineContext<{
apiKey: string;
password: string;
}>({
apiKey: process.env.API_KEY,
password: process.env.PASSWORD,
});
// ✅ Good - Only expose necessary, non-sensitive data
const { t } = defineContext<{
userId: string;
permissions: string[];
}>({
userId: getUserFromSession(request).id,
permissions: getUserPermissions(request),
});Don't expose sensitive information in error messages:
// ❌ Bad - Exposing database details
const getUser = t.query({
args: z.object({ id: z.number() }),
handler: async (ctx, args) => {
try {
return success(await ctx.db.query(
`SELECT * FROM users WHERE id = ${args.id}`
));
} catch (error) {
throw new Error(`Database error: ${error.message}`);
}
},
});
// ✅ Good - Generic error messages
const getUser = t.query({
args: z.object({ id: z.number() }),
handler: async (ctx, args) => {
try {
const user = await ctx.db.users.find(args.id);
if (!user) {
return failureOutcome(Causes.notFound(args.id, 'User'));
}
return success(user);
} catch (error) {
return failureOutcome(
cause({ name: 'InternalError', message: 'Failed to fetch user' })
);
}
},
});Always check permissions in your handlers:
// ✅ Good - Check permissions before action
const deleteUser = t.mutation({
args: z.object({ id: z.number() }),
handler: async (ctx, args) => {
// Check if user has admin permission
if (!ctx.permissions.includes('admin')) {
return failureOutcome(
cause({ name: 'Forbidden', message: 'Insufficient permissions' })
);
}
// Check if user is not deleting themselves
if (args.id === ctx.userId) {
return failureOutcome(
cause({ name: 'InvalidOperation', message: 'Cannot delete yourself' })
);
}
await ctx.db.users.delete(args.id);
return success({ deleted: true });
},
});Implement rate limiting to prevent abuse:
// ✅ Good - Use rate limiting
const sensitiveOperation = t.mutation({
args: z.object({ /* ... */ }),
handler: async (ctx, args) => {
// Check rate limit
const canProceed = await ctx.rateLimit.check(ctx.userId, 'operation', 10, 60000);
if (!canProceed) {
return failureOutcome(
cause({ name: 'RateLimitExceeded', message: 'Too many requests' })
);
}
// Perform operation
return success(await performOperation(args));
},
});We regularly update dependencies to address security vulnerabilities:
- Automated scans: Dependabot automatically scans for vulnerabilities
- Regular audits: Manual security audits before major releases
- Prompt updates: Security patches are prioritized
To keep your project secure:
# Check for vulnerabilities
pnpm audit
# Update dependencies
pnpm update
# Fix vulnerabilities automatically
pnpm audit fix- Type Safety with Zod: Runtime type validation prevents injection attacks
- Context Isolation: Context is defined once and cannot be modified at runtime
- Outcome Types: Structured error handling prevents information leakage
- Lifecycle Hooks: Middleware pattern for security checks
import { defineContext } from '@deessejs/functions';
const { t, createAPI } = defineContext<{
userId: string;
permissions: string[];
}>({
userId: getUserFromSession(),
permissions: getUserPermissions(),
});
// Apply security checks to all mutations
const securedMutation = (mutation) =>
mutation.beforeInvoke((ctx) => {
// Log all mutations
ctx.logger.info('Mutation invoked', { userId: ctx.userId });
// Check if user is verified
if (!ctx.permissions.includes('verified')) {
throw new Error('User not verified');
}
});- Report Received: Security team acknowledges the report
- Investigation: Team validates and assesses the vulnerability
- Development: Security fix is developed and tested
- Release: Security update is released
- Disclosure: Public disclosure with credit to reporter
Security researchers who follow this policy will be credited in the security advisory (unless they prefer to remain anonymous).
Security advisories will be published on GitHub with:
- CVE identifier (if applicable)
- Severity rating (CVSS)
- Affected versions
- Fixed versions
- Mitigation steps
- Credit to reporter
For security-related questions that are not vulnerability reports:
- Email: contact@developerssecrets.com
- PGP Key: Available on request
Thank you for helping keep DeesseJS Functions secure! 🔒