google-gemini / google-gemini/gemini-cli
bug: a single malformed extension directory breaks loading of ALL extensions when allowedExtensions is set
- Dominant language
- TypeScript
- Stars
- 107k
- Forks
- 14.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 45
Description
## What happened?
When `security.allowedExtensions` is configured, `_buildExtension()` throws **outside** the broad try/catch that implements the "skip broken extension" degrade path. A single malformed extension directory then rejects the `Promise.all(subdirs.map(...))` in `loadExtensions()`, making **every** extension unavailable — not just the bad one.
## Affected code
`packages/cli/src/config/extension-manager.ts:720-735` (throws before the try starting at :762):
```ts
const installMetadata = loadInstallMetadata(extensionDir);
let effectiveExtensionPath = extensionDir;
if ((this.settings.security?.allowedExtensions?.length ?? 0) > 0) {
if (!installMetadata?.source) {
throw new Error(
`Failed to load extension ${extensionDir}. The ${INSTALL_METADATA_FILENAME} file is missing or misconfigured.`,
);
}
// ... also throws on invalid regex pattern in allowedExtensions
```
Consumer at `packages/cli/src/config/extension-manager.ts:636`: `await Promise.all(subdirs.map(...))` — one rejection fails all.
## Why this happens easily
`installOrUpdateExtension()` creates the destination directory (`mkdir`, line ~393) **before** writing the metadata file (~442). Any crash/interrupt between those two points leaves exactly the kind of metadata-less directory that now poisons every startup under `allowedExtensions`.
## How can this be reproduced?
1. Set `security.allowedExtensions: ["..."]`.
2. Create an empty directory under `~/.gemini/extensions//`.
3. Start gemini → all extensions fail to load with the "missing or misconfigured" error instead of a per-extension warning.
## What did you expect to happen?
The malformed directory is skipped with a warning (same as the existing catch-path behavior); other extensions load normally.
## Suggested direction
Move the allowedExtensions validation inside the per-extension try/catch, or wrap the whole `_buildExtension` body so any throw maps to `{ fileName, sessionInfo: null }`-style skip with `debugLogger.warn`.
---
*Found by source audit on current `main` (commit `5411f113c`); platform-independent. No open issue/PR covering this was found (searched: allowedExtensions load extension).*
Contributor guide
Research direction
Read packages/cli/src/config/extension-manager.ts around _buildExtension() lines 720-735 and loadExtensions() at line 636. Reproduce with security.allowedExtensions configured and an empty directory under ~/.gemini/extensions/. Done means a malformed extension is skipped with a warning while other extensions continue loading.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 82/100