diegosouzapw/OmniRoute · error · Error

Invalid profile identifier

Error message

Invalid profile identifier

What it means

Sentinel from safePathSegment: after stripping characters outside [a-zA-Z0-9._-] (replaced with _) and truncating to 120 chars, the input collapsed to an empty string, ".", or "..". The value at fault is the VNC profile name input — either the connectionId (persistProfiles mode) or the sessionId used to name the profile directory under VNC_CONFIG.profileDir. A path-traversal/empty-name guard, not a runtime state error.

Solutions

  1. Inspect the connectionId/sessionId passed into createProfileDir — it must contain at least one safe character
  2. Reject or regenerate caller-supplied identifiers that sanitize to nothing
  3. Never bypass the guard: it prevents writing profiles outside the profile root
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at src/lib/vncSession/service.ts:127 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of diegosouzapw/OmniRoute@a179ffed5b (2026-08-25). Data as JSON: /api/errors/cc4b771b3f4df3f7. Report an issue: GitHub.

Appendix: source

Thrown at src/lib/vncSession/service.ts:127

      if (ids.length > 0) {
        await docker(["rm", "-f", ...ids], { timeoutMs: 30_000 });
      }
    })();
  }
  await reconciliationPromise;
}

function findActiveSessionForConnection(connectionId: string): VncSession | undefined {
  return [...SESSIONS.values()].find(
    (session) =>
      session.connectionId === connectionId &&
      ["starting", "running", "harvesting"].includes(session.status)
  );
}

function safePathSegment(value: string): string {
  const safe = value.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 120);
  if (!safe || safe === "." || safe === "..") throw new Error("Invalid profile identifier");
  return safe;
}

function createProfileDir(connectionId: string, sessionId: string): string {
  mkdirSync(VNC_CONFIG.profileDir, { recursive: true, mode: 0o700 });
  chmodSync(VNC_CONFIG.profileDir, 0o700);
  const profileName = safePathSegment(VNC_CONFIG.persistProfiles ? connectionId : sessionId);
  const profileDir = join(VNC_CONFIG.profileDir, profileName);
  mkdirSync(profileDir, { recursive: true, mode: 0o700 });
  chmodSync(profileDir, 0o700);
  return profileDir;
}

async function publishedPort(containerName: string, containerPort: number): Promise<number> {
  const result = await docker(["port", containerName, `${containerPort}/tcp`], {
    timeoutMs: 10_000,
  });
  if (result.code !== 0) {

View on GitHub (pinned to a179ffed5b)