Documentation Index
Fetch the complete documentation index at: https://spec.conveniencepro.cc/llms.txt
Use this file to discover all available pages before exploring further.
Security
CTP defines security requirements to ensure safe tool execution.
Core Principles
Client Privacy
Client-executed tools MUST NOT transmit input data to external servers
Input Validation
All inputs MUST be validated before processing
Safe Defaults
Default configurations MUST be secure
Fail Secure
Errors MUST NOT expose sensitive information
Privacy Requirements
Tools with executionMode: 'client' MUST:
- Execute entirely in the browser
- NOT make network requests with user data
- NOT use tracking or analytics on input
- NOT persist input data beyond the session
// ✅ Correct: Pure client-side processing
export const hashFn: ToolFunction = async (params) => {
const data = new TextEncoder().encode(params.input as string);
const hash = await crypto.subtle.digest('SHA-256', data);
return { success: true, data: { hash: arrayToHex(hash) } };
};
// ❌ Wrong: Sending data to external server
export const hashFn: ToolFunction = async (params) => {
// VIOLATION: Transmitting user input
const response = await fetch('https://api.example.com/hash', {
method: 'POST',
body: JSON.stringify({ input: params.input }),
});
return { success: true, data: await response.json() };
};
Tools with executionMode: 'server':
- MUST document what data is transmitted
- SHOULD use HTTPS for all requests
- MUST handle credentials securely
- SHOULD implement rate limiting
Required Validation
All tools MUST validate:
- Required fields - Presence of required parameters
- Type checking - Parameters match expected types
- Constraints - Values within allowed ranges
- Sanitization - Dangerous content neutralized
export const myFn: ToolFunction = (params) => {
const input = params.input;
// 1. Required check
if (!input) {
return {
success: false,
error: 'Input is required',
errorCode: 'MISSING_REQUIRED',
};
}
// 2. Type check
if (typeof input !== 'string') {
return {
success: false,
error: 'Input must be a string',
errorCode: 'TYPE_ERROR',
};
}
// 3. Constraint check
if (input.length > 100000) {
return {
success: false,
error: 'Input exceeds maximum length of 100,000 characters',
errorCode: 'CONSTRAINT_VIOLATION',
};
}
// 4. Process safely
return { success: true, data: process(input) };
};
Validation Constraints
{
name: 'input',
type: 'textarea',
validation: {
minLength: 1,
maxLength: 100000,
pattern: '^[\\s\\S]*$', // Safe pattern
},
}
Output Security
Safe Error Messages
// ✅ Correct: Generic error message
return {
success: false,
error: 'Invalid input format',
errorCode: 'INVALID_INPUT',
};
// ❌ Wrong: Exposing internal details
return {
success: false,
error: `Database error: ${dbError.message} at ${dbError.stack}`,
errorCode: 'INTERNAL_ERROR',
};
Sanitize Output
When generating HTML or code:
// Escape HTML entities
function escapeHtml(text: string): string {
return text
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
Embedding Security
Content Security Policy
Recommended CSP for embedded tools:
Content-Security-Policy:
default-src 'self';
script-src 'self' https://cdn.conveniencepro.cc;
style-src 'self' 'unsafe-inline';
connect-src 'self';
frame-ancestors 'self' https://*.yourdomain.com;
Iframe Sandboxing
<iframe
src="https://conveniencepro.cc/embed/tool"
sandbox="allow-scripts allow-forms"
referrerpolicy="no-referrer"
></iframe>
Cross-Origin Communication
// Validate message origin
window.addEventListener('message', (event) => {
// Always check origin
if (!trustedOrigins.includes(event.origin)) {
return;
}
// Validate message structure
if (!isValidCTPMessage(event.data)) {
return;
}
handleMessage(event.data);
});
Rate Limiting
Definition
export const myDefinition: ToolDefinition = {
// ...
rateLimit: {
requests: 100, // Max requests
window: 60, // Per 60 seconds
},
};
Runtime Enforcement
import { RateLimiter } from '@conveniencepro/ctp-runtime';
const limiter = new RateLimiter({
requests: 100,
window: 60,
});
const result = await limiter.check('user-id');
if (!result.allowed) {
return {
success: false,
error: `Rate limit exceeded. Try again in ${result.retryAfter} seconds.`,
errorCode: 'RATE_LIMITED',
};
}
Authentication
For tools requiring authentication:
export const myDefinition: ToolDefinition = {
// ...
requiresAuth: true,
};
export const myFn: ToolFunction = async (params, context) => {
// Check authentication
if (!context?.userId) {
return {
success: false,
error: 'Authentication required',
errorCode: 'UNAUTHORIZED',
};
}
// Proceed with authenticated user
return executeForUser(context.userId, params);
};
Security Checklist
Pre-Launch Security Checklist