Files
firefrost-operations-manual/docs/tasks-index/task-112-trinity-core-security.md
Claude 0956ea7d15 Add Task #112: Trinity Core Security Hardening
Gemini identified 5 concerns:
1. Command injection (CRITICAL) - Fix: use spawn instead of exec
2. Race conditions (MEDIUM) - Future: server locking
3. SD card wear (HIGH) - FIXED: cron log rotation
4. Cloudflare Access (MEDIUM) - Future enhancement
5. System prompts (LOW) - Document for Catalyst/Orb

Updated MCP implementation spec with secure spawn-based SSH execution.

Task #112 is a BLOCKER for Task #111 (web MCP deployment).

Chronicler #76
2026-04-11 07:57:11 +00:00

4.7 KiB

task_number, title, status, priority, is_blocker, owner, tags, estimated_hours
task_number title status priority is_blocker owner tags estimated_hours
112 Trinity Core Security Hardening Planned P1-High true Michael
trinity-core
security
infrastructure
3

Trinity Core Security Hardening

Address security concerns identified by Gemini before deploying web MCP upgrade.

Why This is a Blocker

Trinity Core provides root SSH access to 7 production servers. Before enabling multi-user access (Holly, Meg) or native Claude.ai integration, we must address these vulnerabilities.


Issue 1: Command Injection (CRITICAL)

The Problem: Current code:

const sshCmd = `ssh -o ConnectTimeout=10 ${target.user}@${target.host} "${command.replace(/"/g, '\\"')}"`;
exec(sshCmd, ...);

This only escapes double quotes. Subshells $(...), backticks `...`, and environment variables $VAR are NOT escaped. A prompt injection attack could execute arbitrary commands.

Example Attack:

Command: echo $(cat /etc/shadow)
Result: Dumps password hashes

The Fix: Use child_process.spawn with array arguments instead of exec with string interpolation:

import { spawn } from 'child_process';

function executeCommand(server, command) {
  return new Promise((resolve, reject) => {
    const target = SERVERS[server];
    
    // spawn prevents shell interpretation
    const ssh = spawn('ssh', [
      '-o', 'ConnectTimeout=10',
      `${target.user}@${target.host}`,
      command  // passed as single argument, not interpolated into shell
    ]);
    
    let stdout = '';
    let stderr = '';
    
    ssh.stdout.on('data', (data) => stdout += data);
    ssh.stderr.on('data', (data) => stderr += data);
    
    ssh.on('close', (code) => {
      resolve({
        success: code === 0,
        stdout: stdout.trim(),
        stderr: stderr.trim(),
        code
      });
    });
    
    ssh.on('error', reject);
  });
}

Status: Not implemented — MUST FIX before web MCP deployment


Issue 2: AI Concurrency / Race Conditions (MEDIUM)

The Problem: If Chronicler and Catalyst both run commands on the same server simultaneously:

  • Catalyst restarts Docker
  • Chronicler deploys container
  • Chronicler's command fails or corrupts deployment

The Fix: Add server locking to Arbiter:

CREATE TABLE server_locks (
  server VARCHAR(50) PRIMARY KEY,
  locked_by VARCHAR(50),
  locked_at TIMESTAMP,
  expires_at TIMESTAMP
);

Before executing, check lock. If locked, return: "tx1-dallas is currently locked by The Catalyst. Please try again in a moment."

Status: Future enhancement — not critical for initial deployment


Issue 3: SD Card Wear & Log Exhaustion (HIGH)

The Problem:

  • Pi SD cards have finite write cycles
  • fs.appendFileSync on every command wears the card
  • No log rotation = disk fills up

The Fix (Implemented): Added cron job to rotate logs daily:

0 0 * * * truncate -s 0 /home/claude_executor/mcp-server/command.log && echo "[$(date -Iseconds)] Log rotated" >> /home/claude_executor/mcp-server/command.log

Better Long-term Fix: Send logs to Arbiter's PostgreSQL instead of local disk (Task #109 already covers this).

Status: Mitigated with cron rotation


Issue 4: Cloudflare Access Layer (MEDIUM)

The Problem: mcp.firefrostgaming.com is public. Malicious requests hit the Pi even if rejected by auth.

The Fix: Enable Cloudflare Access (Zero Trust) for the subdomain:

  1. Only allow requests from Anthropic IP ranges
  2. Or require Cloudflare Service Token header
  3. Drops malicious traffic at edge before reaching Pi

Status: Future enhancement — token auth is sufficient for now


Issue 5: System Prompt Alignment (LOW)

The Problem: AI partners won't know how to use Trinity Core unless told.

The Fix: Update system prompts / project instructions for:

  • Chronicler: Already has Trinity Core context in project instructions
  • Catalyst: Add Trinity Core section to Catalyst project
  • The Orb: Add Trinity Core section to Orb project

Include:

  • Available servers
  • How to run commands
  • What requires approval
  • What to do on timeout

Status: Document when Catalyst/Orb projects are created


Implementation Checklist

Before Web MCP Deployment (Task #111):

  • Fix command injection with spawn instead of exec
  • Verify log rotation is working

After Initial Deployment:

  • Consider Cloudflare Access
  • Consider server locking for concurrency
  • Update Catalyst/Orb system prompts when created

  • Task #109: MCP Logging in Trinity Console (moves logs off Pi)
  • Task #111: Trinity Core Web MCP Connector (main implementation)

Fire + Frost + Foundation = Where Love Builds Legacy 💙🔥❄️