Generated by Nancy | March 11, 2026
VPC (Virtual PC Control) is a web-based OS-style VPS management dashboard with:
- PostgreSQL management (DB)
- Server monitoring
- File gallery
- API key management
- Web hosting for projects
- Terminal command execution
Tech Stack:
- Backend: Node.js, Express, PostgreSQL (pg)
- Frontend: React 18, Vite, TailwindCSS, Radix UI, Zustand
- Process Manager: PM2
- Reverse Proxy: Nginx
// Rate limiters removed — private system, no throttling neededProblem: Even for private systems, rate limiting prevents brute force attacks. The login endpoint has rate limiting defined in rateLimiter.js but the global limiter is completely disabled.
Risk: Brute force attacks on login, API abuse, DoS potential
case 'sql': {
const sql = parts.slice(2).join(' ').trim();
// ... directly executes user-provided SQL
const result = await projectPool.query(sql);
}Problem: The vpc db <slug> sql <query> command allows executing arbitrary SQL on project databases. While this is behind auth, there's no query sanitization or restrictions.
Risk: Data deletion, data exfiltration, privilege escalation
async function handleDbQuery(command, pool, start) {
const sql = command.replace('vpc db query ', '').trim();
const result = await pool.query(sql);
}Problem: Same issue - arbitrary SQL execution on the main VPC database.
app.use(helmet({
contentSecurityPolicy: false,
crossOriginEmbedderPolicy: false,
crossOriginOpenerPolicy: false,
originAgentCluster: false,
}));Problem: All major Helmet protections are disabled. CSP being off means XSS attacks are easier.
execSync(`git clone --depth 1 -b "${branch}" "${cloneUrl}" "${deployPath}"`, {...});Problem: If branch or cloneUrl contain shell metacharacters, they could be exploited. The branch comes from project.git_branch which is user input.
Risk: Remote code execution
const SECRET = process.env.JWT_SECRET;Problem: No check if JWT_SECRET is actually set. If undefined, JWT signing would fail or use an empty secret.
app.use('/api/db', cors());Problem: The DB external API accepts requests from any origin. While it uses API key auth, this is still a wider attack surface.
- Project names, slugs, and other inputs have minimal validation
- File paths in web hosting could potentially be manipulated
Some routes return generic errors while others expose stack traces or internal messages.
Both app.js:41 and server.js:99 call app.listen(). In production, only app.js should listen, but server.js also has a listen call that will conflict.
Fix: Remove app.listen() from server.js since app.js is the entry point.
/var/www/vpchardcoded in deploy scripts- Various log paths hardcoded with fallbacks
DB creates connection pools per project but there's no visible cleanup when projects are deleted.
localStorage.setItem('vpc-token', data.token);Problem: localStorage is vulnerable to XSS. For a VPS management tool with high privileges, httpOnly cookies would be more secure.
const payload = JSON.parse(atob(token.split('.')[1]));
if (payload.exp * 1000 < Date.now()) {Problem: This can be bypassed by modifying the token. Server-side validation already exists, so this is minor, but the fallback behavior (line 66-72) grants { all: true } permissions if /me fails.
Deploy script doesn't include system package updates.
instances: 1,
autorestart: true,Should add health_check_interval or listen_timeout for production.
- Re-enable rate limiting, at least for public endpoints
- Restrict SQL execution capabilities or add query whitelisting
- Enable Helmet CSP and other security headers
- Sanitize inputs for shell commands (git clone, etc.)
- Move JWT token to httpOnly cookie
- Add JWT_SECRET validation on startup
- Implement proper CORS for DB API
- Add input validation across all routes
- Fix double listen() issue in server.js
- Implement connection pool cleanup
- Standardize error handling
- Remove hardcoded paths, use env vars
- Add health checks to PM2 config
- Add automated security update checks
The VPC project is a solid foundation for a VPS management GUI. The architecture is clean with good separation between frontend/backend. However, there are several security issues that should be addressed before production deployment, especially around:
- SQL injection via terminal commands
- Command injection in git operations
- Disabled security headers
- Missing rate limiting
The code quality is generally good with proper async/await usage, modular structure, and TypeScript-ready patterns in the frontend.
Report generated by Nancy - Yash's AI