google-gemini / google-gemini/gemini-cli
bug: headless mode reports an untrusted folder as trusted to the rest of the app (state/callback mismatch)
- Dominant language
- TypeScript
- Stars
- 107k
- Forks
- 14.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 45
Description
## What happened?
In `useFolderTrust`, the headless branch sets internal state to the **actual** trust value but reports `onTrustChange(true)` — hardcoded — to the parent, unconditionally. When a headless run starts in an untrusted folder, the app-level `isTrustedFolder` becomes `true` while the hook's own state and warning message say the folder is untrusted. Two sources of truth disagree by construction.
## Affected code
`packages/cli/src/ui/hooks/useFolderTrust.ts:70-82`:
```ts
if (isHeadlessMode()) {
if (isMounted) {
setIsTrusted(trusted); // actual value (may be false)
setIsFolderTrustDialogOpen(false);
onTrustChange(true); // hardcoded true
showUntrustedMessage(); // "this folder is untrusted..."
}
} else if (isMounted) {
setIsTrusted(trusted);
setIsFolderTrustDialogOpen(trusted === undefined);
onTrustChange(trusted); // actual value
showUntrustedMessage();
}
```
## Why this is wrong
The parent wires this to `isTrustedFolder` (`AppContainer.tsx`), which feeds trust-gated behavior (include-directory trust prompting via `useIncludeDirsTrust`, UI state consumed by tool gating). In an untrusted folder under `-p/--prompt` headless mode:
- The user is warned "project settings, hooks, MCPs ... will not be applied", yet
- everything keyed off `isTrustedFolder === true` behaves as if trusted.
One of the two values must be wrong; whichever way the product intent goes (headless = treat as trusted, or propagate real value), the current split guarantees inconsistency.
## How can this be reproduced?
1. Mark a folder DO_NOT_TRUST in trusted folders.
2. Run `gemini -p "list files"` inside it.
3. Observe the untrusted banner while app-level trust state is true.
## What did you expect to happen?
A single consistent trust value propagated for the session.
## Suggested direction
Pass the resolved value through in both branches (headless policy, if any, should be applied before calling the hook), e.g., `onTrustChange(isHeadlessMode() ? true : trusted)` only if that is the documented product decision — otherwise `onTrustChange(trusted)`.
---
*Found by source audit on current `main` (commit `5411f113c`); platform-independent. No open issue/PR covering this was found (searched: headless folder trust).*
Contributor guide
Research direction
Start with packages/cli/src/ui/hooks/useFolderTrust.ts:70-82 and trace the callback through AppContainer.tsx into useIncludeDirsTrust. Reproduce with `gemini -p "list files"` in a DO_NOT_TRUST folder, then confirm the chosen headless policy propagates one consistent value to the hook and parent state.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 66/100