Skip to content

Extension commands can shadow core spec-kit commands #1963

@mbachorik

Description

@mbachorik

Problem

An extension can register commands (or aliases) whose output file names collide with core spec-kit commands (analyze, clarify, checklist, constitution, implement, plan, specify, tasks, taskstoissues). When this happens, the extension command overwrites the core command file (e.g. .claude/commands/speckit.analyze.md), effectively hijacking it.

How it happens

  1. Via aliases — command aliases are not validated at all. An extension could declare an alias like speckit.analyze, which would produce the file speckit.analyze.md — directly overwriting the core analyze command.
  2. Via extension ID — while extension command names must follow speckit.{ext}.{cmd} (3 parts), there's no check preventing an extension from using an ID that shadows a core command namespace. An extension with ID analyze would register commands under speckit.analyze.*, creating potential confusion.
  3. Cross-extension conflicts — there's also no check for command name collisions between two different installed extensions.

Relevant code

  • Manifest validation (src/specify_cli/extensions.py:150-160): validates command name pattern speckit.{ext}.{cmd} but does not check against core command names or existing extensions
  • Alias registration (src/specify_cli/agents.py:479-491): aliases are registered without any name format validation
  • Output file naming (src/specify_cli/agents.py:395-404): _compute_output_name derives the file name directly from the command name — no conflict detection

Proposed solution

Add validation during extension add (in install_from_directory / install_from_zip) that:

  1. Rejects command names and aliases that conflict with core commands — maintain a list of core command names and check against it during manifest validation
  2. Rejects command names that conflict with already-installed extensions — check existing registered commands in the extension registry
  3. Validates alias format — aliases should follow the same speckit.{ext}.{cmd} pattern as command names

UX options on conflict

  • Fail with error (recommended for security) — clearly explain which names conflict and suggest renaming
  • Warn and prompt — ask the user if they want to proceed (with --force flag to bypass)

Impact

  • Security: a malicious extension could silently replace core spec-kit commands with arbitrary instructions
  • Reliability: users may not realize a core command has been overwritten until they get unexpected behavior

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions