mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-02 08:19:59 +00:00
fix(auth): prevent default profile from using stale glm env vars
Issue #37: When running `ccs` (default profile), users were unknowingly using GLM API instead of their Claude subscription because: 1. config.json had `default: '~/.claude/settings.json'` entry 2. ProfileDetector treated this as settings-based profile 3. CCS passed `--settings ~/.claude/settings.json` flag to Claude 4. Any stale ANTHROPIC_* env vars in that file got applied Fix (3-pronged approach): - Remove `default` entry from new config.json template - Add migration to remove existing `default: ~/.claude/settings.json` - Add ProfileDetector safety net: if default points to ~/.claude/settings.json, treat as pass-through to Claude's native auth (no --settings flag) Now `ccs` (no profile) correctly uses Claude's native OAuth authentication without loading potentially polluted env vars from previous sessions. Closes #37
This commit is contained in:
+21
-4
@@ -125,12 +125,14 @@ function createConfigFiles() {
|
|||||||
// runs `ccs gemini` or `ccs codex` for first time (requires OAuth auth first)
|
// runs `ccs gemini` or `ccs codex` for first time (requires OAuth auth first)
|
||||||
const configPath = path.join(ccsDir, 'config.json');
|
const configPath = path.join(ccsDir, 'config.json');
|
||||||
if (!fs.existsSync(configPath)) {
|
if (!fs.existsSync(configPath)) {
|
||||||
|
// NOTE: No 'default' entry - when no profile specified, CCS passes through
|
||||||
|
// to Claude's native auth without --settings flag. This prevents env var
|
||||||
|
// pollution from affecting the default profile.
|
||||||
const config = {
|
const config = {
|
||||||
profiles: {
|
profiles: {
|
||||||
glm: '~/.ccs/glm.settings.json',
|
glm: '~/.ccs/glm.settings.json',
|
||||||
glmt: '~/.ccs/glmt.settings.json',
|
glmt: '~/.ccs/glmt.settings.json',
|
||||||
kimi: '~/.ccs/kimi.settings.json',
|
kimi: '~/.ccs/kimi.settings.json'
|
||||||
default: '~/.claude/settings.json'
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -141,23 +143,38 @@ function createConfigFiles() {
|
|||||||
|
|
||||||
console.log('[OK] Created config: ~/.ccs/config.json');
|
console.log('[OK] Created config: ~/.ccs/config.json');
|
||||||
} else {
|
} else {
|
||||||
// Update existing config with glmt if missing (migration for v3.x users)
|
// Update existing config (migration for older versions)
|
||||||
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
||||||
// Ensure profiles object exists
|
// Ensure profiles object exists
|
||||||
if (!config.profiles) {
|
if (!config.profiles) {
|
||||||
config.profiles = {};
|
config.profiles = {};
|
||||||
}
|
}
|
||||||
let configUpdated = false;
|
let configUpdated = false;
|
||||||
|
|
||||||
|
// Migration: Add glmt if missing (v3.x)
|
||||||
if (!config.profiles.glmt) {
|
if (!config.profiles.glmt) {
|
||||||
config.profiles.glmt = '~/.ccs/glmt.settings.json';
|
config.profiles.glmt = '~/.ccs/glmt.settings.json';
|
||||||
configUpdated = true;
|
configUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Migration: Remove 'default' entry pointing to ~/.claude/settings.json (v5.4.0)
|
||||||
|
// This entry caused the default profile to pass --settings flag, which could
|
||||||
|
// pick up stale env vars (ANTHROPIC_BASE_URL) from previous profile sessions.
|
||||||
|
// Fix: Let CCS pass through to Claude's native auth without --settings flag.
|
||||||
|
if (config.profiles.default === '~/.claude/settings.json') {
|
||||||
|
delete config.profiles.default;
|
||||||
|
configUpdated = true;
|
||||||
|
console.log('[OK] Removed legacy default profile (now uses native Claude auth)');
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: gemini/codex profiles added on-demand, not during migration
|
// NOTE: gemini/codex profiles added on-demand, not during migration
|
||||||
if (configUpdated) {
|
if (configUpdated) {
|
||||||
const tmpPath = `${configPath}.tmp`;
|
const tmpPath = `${configPath}.tmp`;
|
||||||
fs.writeFileSync(tmpPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
fs.writeFileSync(tmpPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
||||||
fs.renameSync(tmpPath, configPath);
|
fs.renameSync(tmpPath, configPath);
|
||||||
console.log('[OK] Updated config with glmt profile');
|
if (!config.profiles.glmt) {
|
||||||
|
console.log('[OK] Updated config with glmt profile');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('[OK] Config exists: ~/.ccs/config.json (preserved)');
|
console.log('[OK] Config exists: ~/.ccs/config.json (preserved)');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,10 +178,21 @@ class ProfileDetector {
|
|||||||
const config = this.readConfig();
|
const config = this.readConfig();
|
||||||
|
|
||||||
if (config.profiles && config.profiles['default']) {
|
if (config.profiles && config.profiles['default']) {
|
||||||
|
const settingsPath = config.profiles['default'];
|
||||||
|
// Safety net: If default points to ~/.claude/settings.json, treat as pass-through
|
||||||
|
// to avoid loading stale env vars from previous profile sessions (issue #37).
|
||||||
|
// The ~/.claude/settings.json is Claude's native config - let Claude handle it.
|
||||||
|
if (settingsPath.includes('.claude') && settingsPath.endsWith('settings.json')) {
|
||||||
|
return {
|
||||||
|
type: 'default',
|
||||||
|
name: 'default',
|
||||||
|
message: 'Using native Claude auth (no custom env vars)',
|
||||||
|
};
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
type: 'settings',
|
type: 'settings',
|
||||||
name: 'default',
|
name: 'default',
|
||||||
settingsPath: config.profiles['default'],
|
settingsPath,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user