mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-02 22:17:14 +00:00
fix(claude-extension): enforce private permissions for settings writes (#1378)
This commit is contained in:
@@ -231,8 +231,12 @@ function writeJsonDocument(
|
|||||||
const tempPath = `${filePath}.tmp.${uniqueFileNonce()}`;
|
const tempPath = `${filePath}.tmp.${uniqueFileNonce()}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fs.writeFileSync(tempPath, JSON.stringify(data, null, 2) + '\n', 'utf8');
|
fs.writeFileSync(tempPath, JSON.stringify(data, null, 2) + '\n', {
|
||||||
|
encoding: 'utf8',
|
||||||
|
mode: 0o600,
|
||||||
|
});
|
||||||
fs.renameSync(tempPath, filePath);
|
fs.renameSync(tempPath, filePath);
|
||||||
|
fs.chmodSync(filePath, 0o600);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (fs.existsSync(tempPath)) {
|
if (fs.existsSync(tempPath)) {
|
||||||
fs.rmSync(tempPath, { force: true });
|
fs.rmSync(tempPath, { force: true });
|
||||||
|
|||||||
@@ -313,6 +313,12 @@ describe('web-server claude-extension-routes', () => {
|
|||||||
|
|
||||||
it('creates a binding and applies managed settings to shared + IDE targets', async () => {
|
it('creates a binding and applies managed settings to shared + IDE targets', async () => {
|
||||||
const ideSettingsPath = path.join(tempHome, 'ide', 'vscode', 'settings.json');
|
const ideSettingsPath = path.join(tempHome, 'ide', 'vscode', 'settings.json');
|
||||||
|
const sharedSettingsPath = path.join(tempHome, '.claude', 'settings.json');
|
||||||
|
fs.mkdirSync(path.dirname(ideSettingsPath), { recursive: true });
|
||||||
|
fs.mkdirSync(path.dirname(sharedSettingsPath), { recursive: true });
|
||||||
|
fs.writeFileSync(sharedSettingsPath, JSON.stringify({ env: {} }, null, 2) + '\n', { mode: 0o600 });
|
||||||
|
fs.writeFileSync(ideSettingsPath, JSON.stringify({}, null, 2) + '\n', { mode: 0o600 });
|
||||||
|
|
||||||
const createResponse = await fetch(`${baseUrl}/api/claude-extension/bindings`, {
|
const createResponse = await fetch(`${baseUrl}/api/claude-extension/bindings`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
@@ -352,7 +358,6 @@ describe('web-server claude-extension-routes', () => {
|
|||||||
expect(applied.sharedSettings.state).toBe('applied');
|
expect(applied.sharedSettings.state).toBe('applied');
|
||||||
expect(applied.ideSettings.state).toBe('applied');
|
expect(applied.ideSettings.state).toBe('applied');
|
||||||
|
|
||||||
const sharedSettingsPath = path.join(tempHome, '.claude', 'settings.json');
|
|
||||||
const sharedSettings = JSON.parse(fs.readFileSync(sharedSettingsPath, 'utf8')) as {
|
const sharedSettings = JSON.parse(fs.readFileSync(sharedSettingsPath, 'utf8')) as {
|
||||||
env?: Record<string, string>;
|
env?: Record<string, string>;
|
||||||
};
|
};
|
||||||
@@ -370,6 +375,9 @@ describe('web-server claude-extension-routes', () => {
|
|||||||
)
|
)
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
expect(ideSettings['claudeCode.disableLoginPrompt']).toBe(true);
|
expect(ideSettings['claudeCode.disableLoginPrompt']).toBe(true);
|
||||||
|
|
||||||
|
expect(fs.statSync(sharedSettingsPath).mode & 0o777).toBe(0o600);
|
||||||
|
expect(fs.statSync(ideSettingsPath).mode & 0o777).toBe(0o600);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('resets only managed keys and preserves unrelated shared + IDE settings', async () => {
|
it('resets only managed keys and preserves unrelated shared + IDE settings', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user