Claude-code-plugins-plus-skills replit-policy-guardrails
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/replit-pack/skills/replit-policy-guardrails" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-skills-replit-policy-guardrails && rm -rf "$T"
manifest:
plugins/saas-packs/replit-pack/skills/replit-policy-guardrails/SKILL.mdsource content
Replit Policy Guardrails
Overview
Policy enforcement for Replit-hosted applications. Replit's public-by-default Repls, shared hosting, and resource limits require specific guardrails around secrets exposure, resource consumption, deployment security, and endpoint protection.
Prerequisites
- Replit account with Deployment access
- Understanding of Replit's security model
- Awareness of Replit's Terms of Service
Instructions
Step 1: Secrets Exposure Prevention
Replit Repls are public by default on free plans. Source code is visible to anyone.
# CRITICAL POLICY: Never hardcode secrets in source files # BAD — visible to anyone viewing your Repl API_KEY = "sk-live-abc123" DB_PASSWORD = "p@ssw0rd" # GOOD — use Replit Secrets (AES-256 encrypted) import os API_KEY = os.environ.get("API_KEY") if not API_KEY: raise RuntimeError("API_KEY not set. Add it in the Secrets tab (lock icon).") # Startup validation — fail fast if secrets missing REQUIRED_SECRETS = ["API_KEY", "DATABASE_URL", "JWT_SECRET"] missing = [s for s in REQUIRED_SECRETS if not os.environ.get(s)] if missing: raise RuntimeError(f"Missing required secrets: {missing}")
Automated secret detection:
// Pre-deploy check script: scripts/check-secrets.ts import { readFileSync, readdirSync, statSync } from 'fs'; import { join } from 'path'; const SECRET_PATTERNS = [ /sk[-_](?:live|test)[-_]\w{20,}/, // API keys /(?:password|passwd|pwd)\s*[:=]\s*['"][^'"]+['"]/i, /(?:secret|token)\s*[:=]\s*['"][^'"]{10,}['"]/i, /-----BEGIN (?:RSA |EC )?PRIVATE KEY-----/, /eyJ[A-Za-z0-9-_]+\.eyJ[A-Za-z0-9-_]+/, // JWT tokens ]; function scanFile(filepath: string): string[] { const content = readFileSync(filepath, 'utf-8'); const issues: string[] = []; SECRET_PATTERNS.forEach((pattern, i) => { if (pattern.test(content)) { issues.push(`${filepath}: potential secret found (pattern ${i})`); } }); return issues; } function scanDirectory(dir: string): string[] { const issues: string[] = []; const entries = readdirSync(dir); for (const entry of entries) { if (['.git', 'node_modules', '.cache', 'dist'].includes(entry)) continue; const path = join(dir, entry); if (statSync(path).isDirectory()) { issues.push(...scanDirectory(path)); } else if (/\.(ts|js|py|json|env|yaml|yml|toml)$/.test(entry)) { issues.push(...scanFile(path)); } } return issues; } const issues = scanDirectory('.'); if (issues.length > 0) { console.error('SECRET SCAN FAILED:'); issues.forEach(i => console.error(` ${i}`)); process.exit(1); } console.log('Secret scan passed: no hardcoded secrets found.');
Step 2: Resource Usage Guards
Replit containers have CPU and memory limits. Guard against runaway processes.
import resource import signal import os # Set memory limit (match your deployment tier) MEMORY_LIMIT_MB = int(os.environ.get("MEMORY_LIMIT_MB", "512")) resource.setrlimit( resource.RLIMIT_AS, (MEMORY_LIMIT_MB * 1024 * 1024, MEMORY_LIMIT_MB * 1024 * 1024) ) # Per-request CPU timeout def timeout_handler(signum, frame): raise TimeoutError("Request exceeded CPU time limit") signal.signal(signal.SIGALRM, timeout_handler) @app.route('/process') def process_request(): signal.alarm(30) # 30 second max try: result = heavy_computation() return jsonify(result) except TimeoutError: return jsonify({"error": "Request timed out"}), 504 finally: signal.alarm(0)
// Node.js: memory and request size limits app.use(express.json({ limit: '1mb' })); // Prevent payload bombs app.use(express.urlencoded({ limit: '1mb', extended: true })); // Monitor and alert on high memory setInterval(() => { const heapMB = Math.round(process.memoryUsage().heapUsed / 1024 / 1024); if (heapMB > 400) { // Approaching 512MB limit console.warn(`HIGH MEMORY: ${heapMB}MB — consider restart`); } }, 30000);
Step 3: Endpoint Protection
// Protect all data endpoints with authentication import { Request, Response, NextFunction } from 'express'; function requireAuth(req: Request, res: Response, next: NextFunction) { const userId = req.headers['x-replit-user-id']; if (!userId) { return res.status(401).json({ error: 'Authentication required' }); } next(); } // Apply to all API routes app.use('/api', requireAuth); // Admin-only routes: check specific user IDs or roles function requireAdmin(req: Request, res: Response, next: NextFunction) { const userId = req.headers['x-replit-user-id'] as string; const adminIds = (process.env.ADMIN_USER_IDS || '').split(','); if (!adminIds.includes(userId)) { return res.status(403).json({ error: 'Admin access required' }); } next(); } app.use('/admin', requireAuth, requireAdmin);
Step 4: Deployment Visibility Controls
// Validate deployment configuration at startup function validateDeploymentSecurity() { const warnings: string[] = []; // Check if running as Deployment vs Repl if (!process.env.REPL_DEPLOYMENT && process.env.NODE_ENV === 'production') { warnings.push('WARNING: Production NODE_ENV but not a Deployment. Container may sleep.'); } // Check debug mode if (process.env.DEBUG && process.env.NODE_ENV === 'production') { warnings.push('WARNING: DEBUG enabled in production'); } // Check CORS if (process.env.CORS_ORIGIN === '*' && process.env.NODE_ENV === 'production') { warnings.push('WARNING: CORS allows all origins in production'); } if (warnings.length) { warnings.forEach(w => console.warn(w)); } return { secure: warnings.length === 0, warnings }; } // Run at startup const security = validateDeploymentSecurity(); if (!security.secure) { console.warn('Security warnings detected. Review before production deployment.'); }
Step 5: Security Audit Checklist
## Replit Security Audit ### Secrets (Critical) - [ ] No API keys in source code - [ ] All secrets in Replit Secrets tab - [ ] Startup validates required secrets - [ ] Secret Scanner warnings addressed ### Access Control - [ ] All data endpoints require authentication - [ ] Admin routes have role-based access - [ ] Rate limiting on public endpoints - [ ] CORS configured for specific origins ### Data Protection - [ ] Parameterized SQL queries (no string concatenation) - [ ] Input validation on all user data - [ ] Error responses don't expose internals - [ ] Logs don't contain PII or secrets ### Deployment - [ ] Production uses Deployments (not Repl "Run") - [ ] NODE_ENV set to "production" - [ ] Health endpoint doesn't expose secrets - [ ] Custom domain has SSL (auto-provisioned) ### Resources - [ ] Memory limits appropriate for tier - [ ] Request size limits configured - [ ] Per-request timeout enforced - [ ] Payload size validation
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Secret leaked in code | Not using Secrets tab | Rotate key, move to Secrets |
| OOM kill | No memory limits | Set resource limits, monitor usage |
| Unauthorized data access | Missing auth middleware | Add requireAuth to all /api routes |
| Debug info in production | Debug mode not disabled | Check NODE_ENV and DEBUG env vars |
Resources
Next Steps
For architecture patterns, see
replit-architecture-variants.