-
-
Couldn't load subscription status.
- Fork 9
Security
Haveapp1 edited this page Aug 22, 2025
·
1 revision
Security best practices and guidelines for Agentwise deployment and usage.
Security is a critical consideration when using Agentwise, especially for enterprise applications and proprietary projects. This guide covers comprehensive security practices, threat mitigation, and compliance considerations.
βββββββββββββββββββββββββββββββββββββββββββββ
β Application Security Layer β β Input validation, sanitization
βββββββββββββββββββββββββββββββββββββββββββββ€
β Authentication & Authorization β β API keys, JWT, RBAC
βββββββββββββββββββββββββββββββββββββββββββββ€
β Network Security Layer β β TLS, firewall rules
βββββββββββββββββββββββββββββββββββββββββββββ€
β Data Protection β β Encryption at rest/transit
βββββββββββββββββββββββββββββββββββββββββββββ€
β Infrastructure Security β β Container security, OS hardening
βββββββββββββββββββββββββββββββββββββββββββββ
// Secure API key configuration
{
"security": {
"apiKeys": {
"required": true,
"rotation": "30d",
"minLength": 32,
"algorithm": "HS256"
}
}
}Best Practices:
- Store API keys in environment variables, never in code
- Rotate keys regularly (recommended: monthly)
- Use different keys for different environments
- Implement key rotation without service interruption
# Secure API key management
export AGENTWISE_API_KEY="$(cat /secure/path/api-key.txt)"
export CLAUDE_API_KEY="$(cat /secure/path/claude-key.txt)"
# Key rotation script
#!/bin/bash
NEW_KEY=$(generate_api_key)
echo $NEW_KEY > /secure/path/new-api-key.txt
# Test with new key
if test_api_key $NEW_KEY; then
mv /secure/path/new-api-key.txt /secure/path/api-key.txt
restart_agentwise_service
fi// RBAC configuration
{
"security": {
"roles": {
"admin": {
"permissions": [
"agents:*",
"projects:*",
"config:*",
"users:*"
]
},
"developer": {
"permissions": [
"projects:create",
"projects:read",
"agents:read",
"tasks:*"
]
},
"viewer": {
"permissions": [
"projects:read",
"agents:read",
"tasks:read"
]
}
},
"users": {
"john.doe@company.com": { "role": "developer" },
"admin@company.com": { "role": "admin" }
}
}
}At Rest:
{
"security": {
"encryption": {
"algorithm": "AES-256-GCM",
"keyRotation": "90d",
"targets": [
"configuration_files",
"cached_data",
"project_artifacts",
"logs"
]
}
}
}In Transit:
- All API communications use TLS 1.3
- Certificate pinning for critical connections
- Perfect Forward Secrecy (PFS) enabled
class DataSanitizer {
sanitizeInput(data) {
// Remove sensitive patterns
const sanitized = data
.replace(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g, '[EMAIL]')
.replace(/\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g, '[CARD]')
.replace(/\b\d{3}-\d{2}-\d{4}\b/g, '[SSN]')
.replace(/sk-[a-zA-Z0-9]{48}/g, '[API_KEY]');
return sanitized;
}
sanitizeForLogging(data) {
return {
...data,
apiKey: '[REDACTED]',
password: '[REDACTED]',
token: '[REDACTED]'
};
}
}{
"security": {
"fileAccess": {
"allowedPaths": [
"/app/projects/**",
"/app/templates/**",
"/app/public/**"
],
"deniedPaths": [
"/etc/**",
"/root/**",
"**/.env",
"**/.git/**",
"**/node_modules/**",
"**/*.key",
"**/*.pem"
],
"maxFileSize": "10MB",
"allowedExtensions": [
".js", ".ts", ".jsx", ".tsx",
".py", ".java", ".go",
".json", ".yaml", ".md",
".css", ".scss", ".html"
]
}
}
}class SecureFileOperations {
async readFile(filePath) {
// Validate path
if (!this.isPathAllowed(filePath)) {
throw new SecurityError(`Access denied: ${filePath}`);
}
// Prevent directory traversal
const resolvedPath = path.resolve(filePath);
if (!resolvedPath.startsWith(this.getAllowedBasePath())) {
throw new SecurityError('Directory traversal attempt detected');
}
// Check file size
const stats = await fs.stat(resolvedPath);
if (stats.size > this.maxFileSize) {
throw new SecurityError('File too large');
}
return await fs.readFile(resolvedPath, 'utf8');
}
}// Secure server configuration
const tlsOptions = {
minVersion: 'TLSv1.3',
ciphers: [
'TLS_AES_256_GCM_SHA384',
'TLS_CHACHA20_POLY1305_SHA256',
'TLS_AES_128_GCM_SHA256'
],
honorCipherOrder: true,
secureProtocol: 'TLS_method'
};
const server = https.createServer(tlsOptions, app);# UFW firewall configuration
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow SSH (change port as needed)
sudo ufw allow 22/tcp
# Allow Agentwise API (if exposed)
sudo ufw allow 3001/tcp
# Allow specific outbound connections only
sudo ufw allow out 443/tcp # HTTPS
sudo ufw allow out 80/tcp # HTTP
sudo ufw allow out 53/tcp # DNS
sudo ufw enable# Secure Dockerfile
FROM node:18-alpine AS builder
# Create non-root user
RUN addgroup -g 1001 -S agentwise && \
adduser -S agentwise -u 1001 -G agentwise
# Set working directory
WORKDIR /app
# Copy and install dependencies
COPY package*.json ./
RUN npm ci --only=production && \
npm cache clean --force
# Copy application code
COPY --chown=agentwise:agentwise . .
# Remove unnecessary packages
RUN apk del build-dependencies
# Switch to non-root user
USER agentwise
# Expose port
EXPOSE 3001
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node healthcheck.js
# Start application
CMD ["npm", "start"]apiVersion: v1
kind: SecurityContext
metadata:
name: agentwise-security-context
spec:
runAsNonRoot: true
runAsUser: 1001
runAsGroup: 1001
fsGroup: 1001
seccompProfile:
type: RuntimeDefault
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: agentwise-network-policy
spec:
podSelector:
matchLabels:
app: agentwise
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: authorized-namespace
ports:
- protocol: TCP
port: 3001
egress:
- to: []
ports:
- protocol: TCP
port: 443 # HTTPS onlyconst joi = require('joi');
const taskSchema = joi.object({
description: joi.string().max(1000).required(),
type: joi.string().valid('frontend', 'backend', 'database', 'testing').required(),
requirements: joi.object().max(10).required(),
priority: joi.string().valid('low', 'medium', 'high').default('medium'),
tokenBudget: joi.number().min(1000).max(100000).default(5000)
});
app.post('/api/v1/tasks', async (req, res) => {
try {
const { error, value } = taskSchema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
// Process validated input
const result = await taskService.createTask(value);
res.json(result);
} catch (err) {
logger.error('Task creation failed', { error: err.message });
res.status(500).json({ error: 'Internal server error' });
}
});class SecurityAuditLogger {
constructor() {
this.logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'security-audit.log' }),
new winston.transports.Console()
]
});
}
logAuthentication(event, userId, success, details = {}) {
this.logger.info('Authentication Event', {
event,
userId,
success,
timestamp: new Date().toISOString(),
ip: details.ip,
userAgent: details.userAgent
});
}
logFileAccess(event, userId, filePath, success, details = {}) {
this.logger.info('File Access Event', {
event,
userId,
filePath: this.sanitizePath(filePath),
success,
timestamp: new Date().toISOString(),
operation: details.operation
});
}
logSecurityViolation(violation, userId, details = {}) {
this.logger.warn('Security Violation', {
violation,
userId,
timestamp: new Date().toISOString(),
details: this.sanitizeDetails(details)
});
}
}const rateLimit = require('express-rate-limit');
// API rate limiting
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: 'Too many requests from this IP',
standardHeaders: true,
legacyHeaders: false
});
// Stricter limits for sensitive endpoints
const strictLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 5, // 5 requests per minute
skipSuccessfulRequests: true
});
app.use('/api/', apiLimiter);
app.use('/api/v1/auth/', strictLimiter);
app.use('/api/v1/config/', strictLimiter);class IntrusionDetectionSystem {
constructor() {
this.suspiciousPatterns = [
/\.\.\//g, // Directory traversal
/<script/gi, // XSS attempts
/union.*select/gi, // SQL injection
/eval\(/gi, // Code injection
/exec\(/gi // Command injection
];
this.failedAttempts = new Map();
}
detectThreats(request) {
const threats = [];
// Check for suspicious patterns
const payload = JSON.stringify(request.body);
for (const pattern of this.suspiciousPatterns) {
if (pattern.test(payload)) {
threats.push({
type: 'malicious_payload',
pattern: pattern.source,
severity: 'high'
});
}
}
// Check for brute force
const ip = request.ip;
const attempts = this.failedAttempts.get(ip) || 0;
if (attempts > 10) {
threats.push({
type: 'brute_force',
attempts,
severity: 'critical'
});
}
return threats;
}
}# .env.production (example - use secret management in production)
NODE_ENV=production
AGENTWISE_API_KEY="${AGENTWISE_API_KEY}"
CLAUDE_API_KEY="${CLAUDE_API_KEY}"
DATABASE_URL="${DATABASE_URL}"
REDIS_URL="${REDIS_URL}"
JWT_SECRET="${JWT_SECRET}"
ENCRYPTION_KEY="${ENCRYPTION_KEY}"
# Security headers
HSTS_MAX_AGE=31536000
CSP_POLICY="default-src 'self'; script-src 'self' 'unsafe-inline'"
X_FRAME_OPTIONS="DENY"// Using HashiCorp Vault
const vault = require('node-vault')({
endpoint: process.env.VAULT_ENDPOINT,
token: process.env.VAULT_TOKEN
});
class SecretsManager {
async getSecret(path) {
try {
const result = await vault.read(path);
return result.data;
} catch (error) {
logger.error('Failed to retrieve secret', { path, error: error.message });
throw new Error('Secret retrieval failed');
}
}
async rotateSecret(path, newValue) {
try {
await vault.write(path, { value: newValue });
logger.info('Secret rotated successfully', { path });
} catch (error) {
logger.error('Failed to rotate secret', { path, error: error.message });
throw new Error('Secret rotation failed');
}
}
}// SOC 2 controls implementation
const soc2Controls = {
CC6_1: 'Logical access security measures',
CC6_2: 'User access provisioning and deprovisioning',
CC6_3: 'User access authentication',
CC6_7: 'Data transmission security',
CC6_8: 'Data disposal'
};
class ComplianceManager {
async auditAccessControls() {
// Implement access control auditing
const users = await this.getAllUsers();
const violations = [];
for (const user of users) {
if (!user.lastLogin || Date.now() - user.lastLogin > 90 * 24 * 60 * 60 * 1000) {
violations.push({
type: 'inactive_user',
user: user.id,
lastLogin: user.lastLogin
});
}
}
return violations;
}
}class IncidentResponse {
async handleSecurityIncident(incident) {
// Log incident
securityLogger.logSecurityViolation(incident.type, incident.userId, incident);
// Immediate response based on severity
switch (incident.severity) {
case 'critical':
await this.lockUserAccount(incident.userId);
await this.alertSecurityTeam(incident);
await this.initiateForensics(incident);
break;
case 'high':
await this.requireReauthentication(incident.userId);
await this.alertSecurityTeam(incident);
break;
case 'medium':
await this.logForReview(incident);
break;
}
}
async generateIncidentReport(incidentId) {
const incident = await this.getIncident(incidentId);
return {
id: incident.id,
timestamp: incident.timestamp,
type: incident.type,
severity: incident.severity,
affectedSystems: incident.affectedSystems,
responseActions: incident.responseActions,
resolution: incident.resolution,
lessonsLearned: incident.lessonsLearned
};
}
}class SecurityDashboard {
getSecurityMetrics() {
return {
activeThreats: this.getActiveThreats(),
failedLogins: this.getFailedLoginCount(),
suspiciousActivity: this.getSuspiciousActivityCount(),
systemHealth: this.getSystemHealthStatus(),
complianceStatus: this.getComplianceStatus()
};
}
async generateSecurityReport() {
const metrics = this.getSecurityMetrics();
const incidents = await this.getRecentIncidents();
const vulnerabilities = await this.getVulnerabilities();
return {
summary: metrics,
incidents,
vulnerabilities,
recommendations: this.getSecurityRecommendations()
};
}
}- All API keys stored in environment variables
- Input validation on all endpoints
- Output sanitization implemented
- Rate limiting configured
- HTTPS enforced everywhere
- Security headers implemented
- Dependency vulnerability scanning enabled
- Code security reviews conducted
- Non-root user containers
- Network policies configured
- Secrets management implemented
- Audit logging enabled
- Monitoring and alerting configured
- Backup and recovery tested
- Incident response plan documented
- Security training completed
- Regular security assessments
- Vulnerability patching schedule
- Access review quarterly
- Log monitoring active
- Incident response tested
- Compliance audits current
- Security metrics tracked
- Team security training updated
For more information, see Configuration, Privacy, or Troubleshooting.
Support
- Discord: @vibecodingwithphil
- GitHub: @VibeCodingWithPhil