fix(cursor): redact daemon token from dashboard start (#1540)

Redacts the Cursor daemon token from dashboard start output.
This commit is contained in:
Kai (Tam Nhu) Tran authored and GitHub committed 2026-06-15 23:24:37 -04:00
1 parent 74dd2f38cc
commit b85a3de26e
2 files changed
+40 -30

No files matched your search

+3 -1
View File
@@ -234,7 +234,9 @@ router.post('/daemon/start', async (_req: Request, res: Response): Promise<void>
port: cursorConfig.port, port: cursorConfig.port,
ghost_mode: cursorConfig.ghost_mode, ghost_mode: cursorConfig.ghost_mode,
}); });
res.json(result); const { daemonToken: _redactedDaemonToken, ...publicResult } = result;
void _redactedDaemonToken;
res.json(publicResult);
} catch (error) { } catch (error) {
res.status(500).json({ error: (error as Error).message }); res.status(500).json({ error: (error as Error).message });
} }
+37 -29
View File
@@ -52,9 +52,11 @@ let checkAuthStatus: () => {
}; };
}; };
let getTokenStoragePath: () => string; let getTokenStoragePath: () => string;
let getDaemonStartPreconditionError: ( let getDaemonStartPreconditionError: (input: {
input: { enabled: boolean; authenticated: boolean; tokenExpired?: boolean } enabled: boolean;
) => { status: number; error: string } | null; authenticated: boolean;
tokenExpired?: boolean;
}) => { status: number; error: string } | null;
let getAutoDetectFailureStatus: ( let getAutoDetectFailureStatus: (
reason?: reason?:
| 'db_not_found' | 'db_not_found'
@@ -65,13 +67,15 @@ let getAutoDetectFailureStatus: (
| 'invalid_token_format' | 'invalid_token_format'
) => number; ) => number;
function seedCursorConfig(overrides: { function seedCursorConfig(
enabled?: boolean; overrides: {
port?: number; enabled?: boolean;
auto_start?: boolean; port?: number;
ghost_mode?: boolean; auto_start?: boolean;
model?: string; ghost_mode?: boolean;
} = {}): void { model?: string;
} = {}
): void {
const config = loadOrCreateUnifiedConfig(); const config = loadOrCreateUnifiedConfig();
config.cursor = { config.cursor = {
enabled: overrides.enabled ?? true, enabled: overrides.enabled ?? true,
@@ -329,7 +333,10 @@ describe('Cursor Routes Logic', () => {
try { try {
const dbPath = getTokenStoragePath(); const dbPath = getTokenStoragePath();
fs.mkdirSync(path.dirname(dbPath), { recursive: true }); fs.mkdirSync(path.dirname(dbPath), { recursive: true });
execFileSync('sqlite3', [dbPath, 'CREATE TABLE IF NOT EXISTS itemTable (key TEXT PRIMARY KEY, value TEXT);']); execFileSync('sqlite3', [
dbPath,
'CREATE TABLE IF NOT EXISTS itemTable (key TEXT PRIMARY KEY, value TEXT);',
]);
execFileSync('sqlite3', [ execFileSync('sqlite3', [
dbPath, dbPath,
`INSERT OR REPLACE INTO itemTable (key, value) VALUES ('cursorAuth/accessToken', '${token}');`, `INSERT OR REPLACE INTO itemTable (key, value) VALUES ('cursorAuth/accessToken', '${token}');`,
@@ -471,27 +478,28 @@ describe('Cursor Routes Logic', () => {
expect(json.error).toContain('expired'); expect(json.error).toContain('expired');
}); });
it( it('POST /api/cursor/daemon/start starts daemon and /daemon/stop stops it', async () => {
'POST /api/cursor/daemon/start starts daemon and /daemon/stop stops it', const port = 15000 + Math.floor(Math.random() * 20000);
async () => { seedCursorConfig({ enabled: true, port });
const port = 15000 + Math.floor(Math.random() * 20000); seedCredentials(false);
seedCursorConfig({ enabled: true, port });
seedCredentials(false);
const startRes = await fetch(`${baseUrl}/api/cursor/daemon/start`, { method: 'POST' }); const startRes = await fetch(`${baseUrl}/api/cursor/daemon/start`, { method: 'POST' });
expect(startRes.status).toBe(200); expect(startRes.status).toBe(200);
const startJson = (await startRes.json()) as { success?: boolean; pid?: number }; const startJson = (await startRes.json()) as {
expect(startJson.success).toBe(true); success?: boolean;
expect(typeof startJson.pid).toBe('number'); pid?: number;
daemonToken?: string;
};
expect(startJson.success).toBe(true);
expect(typeof startJson.pid).toBe('number');
expect(startJson.daemonToken).toBeUndefined();
const stopRes = await fetch(`${baseUrl}/api/cursor/daemon/stop`, { method: 'POST' }); const stopRes = await fetch(`${baseUrl}/api/cursor/daemon/stop`, { method: 'POST' });
expect(stopRes.status).toBe(200); expect(stopRes.status).toBe(200);
const stopJson = (await stopRes.json()) as { success?: boolean }; const stopJson = (await stopRes.json()) as { success?: boolean };
expect(stopJson.success).toBe(true); expect(stopJson.success).toBe(true);
}, }, 35000);
35000
);
it('POST /api/cursor/daemon/stop returns success when daemon is not running', async () => { it('POST /api/cursor/daemon/stop returns success when daemon is not running', async () => {
const res = await fetch(`${baseUrl}/api/cursor/daemon/stop`, { method: 'POST' }); const res = await fetch(`${baseUrl}/api/cursor/daemon/stop`, { method: 'POST' });