GATE007: Unpinned MCP package
An MCP server is launched with a package runner and no pinned version.
- Name
Severity- Type
- Medium
- Description
Default severity. An individual finding may be reported higher or lower when the surrounding configuration justifies it.
- Name
Explain locally- Type
- gate explain GATE007
- Description
The same text, in your terminal, with no network access.
What Gate detected
Gate found an MCP server started with npx, bunx, uvx, pnpm dlx, yarn dlx or pipx where the package specifier has no exact version, or is pinned to a moving tag such as @latest. Auto-confirm flags (-y, --yes) are noted because they remove the one prompt that would otherwise show you what is about to be installed.
Why this matters
An unpinned package runner resolves and executes whatever the registry serves at that moment, with no lockfile and no review. That means a compromised maintainer account, a hijacked package name, or a typosquat takes effect on the next agent start: inside a process you have already handed your credentials to.
This is a lower severity than the execution rules because it is a conditional risk: it requires an upstream compromise. It is on the list because agent configuration is one of the few remaining places where developers routinely run unpinned code by default.
Example
This is the shape of configuration that triggers the rule.
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"]
}
}
}
And a safer version of the same thing:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github@2025.4.8"]
}
}
}
Remediation
Pin the exact version, and update it deliberately. Better still, add the server as a project dependency so it is covered by your lockfile, your dependency scanner and your review process.
Suppressing this rule
If this finding is acceptable in your repository, record why alongside the suppression:
gate.config.ts
export default defineConfig({
ignore: [
{
rule: 'GATE007',
reason: 'Why this is acceptable here',
},
],
})
Gate refuses to apply an ignore entry with no reason. The reason is the only thing that will tell the next person whether the suppression is still true.