google-gemini / google-gemini/gemini-cli

bug: a single malformed extension directory breaks loading of ALL extensions when allowedExtensions is set

Open Beginner friendly
#29,035 2 comments 0 reactions 0 assignees View on GitHub
area/extensions effort/small status/bot-triaged
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.