mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-03 16:34:31 -07:00
feat(cli): secure .env loading and enforce workspace trust in headless mode (#25814)
Co-authored-by: galz10 <galzahavi@google.com> Co-authored-by: davidapierce <davidapierce@google.com>
This commit is contained in:
@@ -34,6 +34,7 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
|
||||
...actual,
|
||||
homedir: () => os.homedir(),
|
||||
getCompatibilityWarnings: vi.fn().mockReturnValue([]),
|
||||
isHeadlessMode: vi.fn().mockReturnValue(false),
|
||||
WarningPriority: {
|
||||
Low: 'low',
|
||||
High: 'high',
|
||||
@@ -143,6 +144,51 @@ describe('getUserStartupWarnings', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('folder trust check', () => {
|
||||
it('should throw FatalUntrustedWorkspaceError when untrusted in headless mode', async () => {
|
||||
const { isHeadlessMode, FatalUntrustedWorkspaceError } = await import(
|
||||
'@google/gemini-cli-core'
|
||||
);
|
||||
vi.mocked(isFolderTrustEnabled).mockReturnValue(true);
|
||||
vi.mocked(isWorkspaceTrusted).mockImplementation(() => {
|
||||
throw new FatalUntrustedWorkspaceError(
|
||||
'Gemini CLI is not running in a trusted directory',
|
||||
);
|
||||
});
|
||||
vi.mocked(isHeadlessMode).mockReturnValue(true);
|
||||
|
||||
await expect(
|
||||
getUserStartupWarnings({}, testRootDir),
|
||||
).rejects.toThrowError(FatalUntrustedWorkspaceError);
|
||||
});
|
||||
|
||||
it('should not return a warning when trusted in headless mode', async () => {
|
||||
const { isHeadlessMode } = await import('@google/gemini-cli-core');
|
||||
vi.mocked(isFolderTrustEnabled).mockReturnValue(true);
|
||||
vi.mocked(isWorkspaceTrusted).mockReturnValue({
|
||||
isTrusted: true,
|
||||
source: 'file',
|
||||
});
|
||||
vi.mocked(isHeadlessMode).mockReturnValue(true);
|
||||
|
||||
const warnings = await getUserStartupWarnings({}, testRootDir);
|
||||
expect(warnings.find((w) => w.id === 'folder-trust')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not return a warning when untrusted in interactive mode', async () => {
|
||||
const { isHeadlessMode } = await import('@google/gemini-cli-core');
|
||||
vi.mocked(isFolderTrustEnabled).mockReturnValue(true);
|
||||
vi.mocked(isWorkspaceTrusted).mockReturnValue({
|
||||
isTrusted: false,
|
||||
source: undefined,
|
||||
});
|
||||
vi.mocked(isHeadlessMode).mockReturnValue(false);
|
||||
|
||||
const warnings = await getUserStartupWarnings({}, testRootDir);
|
||||
expect(warnings.find((w) => w.id === 'folder-trust')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('compatibility warnings', () => {
|
||||
it('should include compatibility warnings by default', async () => {
|
||||
const compWarning = {
|
||||
|
||||
@@ -12,6 +12,8 @@ import {
|
||||
getCompatibilityWarnings,
|
||||
WarningPriority,
|
||||
type StartupWarning,
|
||||
isHeadlessMode,
|
||||
FatalUntrustedWorkspaceError,
|
||||
} from '@google/gemini-cli-core';
|
||||
import type { Settings } from '../config/settingsSchema.js';
|
||||
import {
|
||||
@@ -79,10 +81,34 @@ const rootDirectoryCheck: WarningCheck = {
|
||||
},
|
||||
};
|
||||
|
||||
const folderTrustCheck: WarningCheck = {
|
||||
id: 'folder-trust',
|
||||
priority: WarningPriority.High,
|
||||
check: async (workspaceRoot: string, settings: Settings) => {
|
||||
if (!isFolderTrustEnabled(settings)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { isTrusted } = isWorkspaceTrusted(settings, workspaceRoot);
|
||||
if (isTrusted === true) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isHeadlessMode()) {
|
||||
throw new FatalUntrustedWorkspaceError(
|
||||
'Gemini CLI is not running in a trusted directory. To proceed, either use `--skip-trust`, set the `GEMINI_CLI_TRUST_WORKSPACE=true` environment variable, or trust this directory in interactive mode.',
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
};
|
||||
|
||||
// All warning checks
|
||||
const WARNING_CHECKS: readonly WarningCheck[] = [
|
||||
homeDirectoryCheck,
|
||||
rootDirectoryCheck,
|
||||
folderTrustCheck,
|
||||
];
|
||||
|
||||
export async function getUserStartupWarnings(
|
||||
|
||||
Reference in New Issue
Block a user