@zereight/mcp-gitlab 2.3.7-next.138 → 2.3.7-next.139

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ko.md CHANGED
@@ -213,7 +213,7 @@ CLI 인자는 환경 변수보다 우선합니다.
213
213
 
214
214
  > [!CAUTION]
215
215
  > `gitlab_api_request`(`api` 툴셋)는 `GITLAB_ALLOWED_GROUPS`와 그 밖의 그룹 제한, 프로젝트 허용 목록, 도구 단위 제한(`GITLAB_TOOLS`, 다른 도구에 걸린 `GITLAB_DENIED_TOOLS_REGEX`), 개별 도구 안전 검사를 우회합니다. 토큰 권한 범위 전체가 노출됩니다. 프롬프트 인젝션이 이 도구를 호출할 수 있습니다. 이런 제한에 의존하는 운영자는 켜면 안 됩니다.
216
- > `GITLAB_TOOLSETS`에 `api`를 직접 적을 때만 켜집니다 (`GITLAB_TOOLSETS=all`, `discover_tools`, `GITLAB_TOOLS`, 레거시 `USE_*`, `GITLAB_TOOL_PROFILE`로는 안 됩니다). `GITLAB_ALLOWED_PROJECT_IDS`는 `/projects/:id` 경로만 검사합니다. `/search`, `/users`, `/groups/:id`, `/runners` 같은 엔드포인트는 제한되지 않습니다. `GITLAB_PROJECT_ID`와 OAuth 그룹 허용 목록은 이 도구가 검사하지 않습니다.
216
+ > `GITLAB_TOOLSETS`에 `api`를 직접 적을 때만 켜집니다 (`GITLAB_TOOLSETS=all`, `discover_tools`, `GITLAB_TOOLS`, 레거시 `USE_*`, `GITLAB_TOOL_PROFILE`로는 안 됩니다). `GITLAB_ALLOWED_PROJECT_IDS`나 세션 프로젝트 범위가 있으면 허용된 프로젝트의 `/projects/:id` 경로만 받습니다. `/search`, `/users`, `/groups/:id`, `/runners` 같은 엔드포인트는 거부됩니다. 본문과 쿼리 파라미터가 가리키는 다른 프로젝트는 검사하지 않습니다. `GITLAB_PROJECT_ID`와 OAuth 그룹 허용 목록은 이 도구가 검사하지 않습니다.
217
217
 
218
218
  - sse
219
219
 
package/README.md CHANGED
@@ -219,7 +219,7 @@ The same binary is also a `gh`-style GitLab CLI (`tool <name>` or curated forms
219
219
 
220
220
  > [!CAUTION]
221
221
  > `gitlab_api_request` (toolset `api`) bypasses `GITLAB_ALLOWED_GROUPS` and other group restrictions, project allowlists, tool-level restrictions (`GITLAB_TOOLS`, `GITLAB_DENIED_TOOLS_REGEX` on other tools), and individual tool safety checks. The full token permission scope is exposed. Prompt injection can drive this tool. Operators who rely on these restrictions must NOT enable it.
222
- > Enable it only by listing `api` in `GITLAB_TOOLSETS` (`GITLAB_TOOLSETS=all`, `discover_tools`, `GITLAB_TOOLS`, legacy `USE_*` flags, and `GITLAB_TOOL_PROFILE` do not). `GITLAB_ALLOWED_PROJECT_IDS` is checked only for `/projects/:id` paths. Endpoints such as `/search`, `/users`, `/groups/:id`, and `/runners` are not constrained. `GITLAB_PROJECT_ID` and OAuth group allowlists are not enforced.
222
+ > Enable it only by listing `api` in `GITLAB_TOOLSETS` (`GITLAB_TOOLSETS=all`, `discover_tools`, `GITLAB_TOOLS`, legacy `USE_*` flags, and `GITLAB_TOOL_PROFILE` do not). With `GITLAB_ALLOWED_PROJECT_IDS` or a session project scope, only `/projects/:id` paths for an allowed project are accepted. Endpoints such as `/search`, `/users`, `/groups/:id`, and `/runners` are rejected. Body and query parameters that name another project are not checked. `GITLAB_PROJECT_ID` and OAuth group allowlists are not enforced.
223
223
 
224
224
  - sse
225
225
 
package/README.pt-BR.md CHANGED
@@ -213,7 +213,7 @@ O mesmo binário também é uma CLI do GitLab no estilo `gh` (`tool <name>` ou f
213
213
 
214
214
  > [!CAUTION]
215
215
  > `gitlab_api_request` (toolset `api`) ignora `GITLAB_ALLOWED_GROUPS` e outras restrições de grupo, allowlists de projeto, restrições por ferramenta (`GITLAB_TOOLS`, `GITLAB_DENIED_TOOLS_REGEX` nas outras ferramentas) e as checagens de segurança de cada ferramenta. O escopo completo do token fica exposto. Prompt injection pode acionar esta ferramenta. Operadores que dependem dessas restrições NÃO devem habilitá-la.
216
- > Ela só liga quando `api` está listado em `GITLAB_TOOLSETS` (`GITLAB_TOOLSETS=all`, `discover_tools`, `GITLAB_TOOLS`, flags legadas `USE_*` e `GITLAB_TOOL_PROFILE` não ligam). `GITLAB_ALLOWED_PROJECT_IDS` vale só para caminhos `/projects/:id`. Endpoints como `/search`, `/users`, `/groups/:id` e `/runners` não são restringidos. `GITLAB_PROJECT_ID` e allowlists de grupo OAuth não são aplicados por esta ferramenta.
216
+ > Ela só liga quando `api` está listado em `GITLAB_TOOLSETS` (`GITLAB_TOOLSETS=all`, `discover_tools`, `GITLAB_TOOLS`, flags legadas `USE_*` e `GITLAB_TOOL_PROFILE` não ligam). Com `GITLAB_ALLOWED_PROJECT_IDS` ou um escopo de projeto da sessão, só caminhos `/projects/:id` de um projeto permitido são aceitos. Endpoints como `/search`, `/users`, `/groups/:id` e `/runners` são rejeitados. Parâmetros de corpo e de query que apontam para outro projeto não são verificados. `GITLAB_PROJECT_ID` e allowlists de grupo OAuth não são aplicados por esta ferramenta.
217
217
 
218
218
  - sse
219
219
 
package/README.zh-CN.md CHANGED
@@ -212,7 +212,7 @@ CLI 参数优先于环境变量。
212
212
 
213
213
  > [!CAUTION]
214
214
  > `gitlab_api_request`(`api` 工具集)会绕过 `GITLAB_ALLOWED_GROUPS` 及其他群组限制、项目允许列表、工具级限制(`GITLAB_TOOLS`、作用在其他工具上的 `GITLAB_DENIED_TOOLS_REGEX`)以及各个工具自己的安全检查。令牌的完整权限范围都会暴露。提示注入可以驱动这个工具。依赖这些限制的运维人员不得启用它。
215
- > 只有在 `GITLAB_TOOLSETS` 中显式写入 `api` 时才会启用(`GITLAB_TOOLSETS=all`、`discover_tools`、`GITLAB_TOOLS`、旧版 `USE_*`、`GITLAB_TOOL_PROFILE` 都不会)。`GITLAB_ALLOWED_PROJECT_IDS` 只检查 `/projects/:id` 路径。`/search`、`/users`、`/groups/:id`、`/runners` 等端点不受约束。`GITLAB_PROJECT_ID` 和 OAuth 群组允许列表不会被此工具强制执行。
215
+ > 只有在 `GITLAB_TOOLSETS` 中显式写入 `api` 时才会启用(`GITLAB_TOOLSETS=all`、`discover_tools`、`GITLAB_TOOLS`、旧版 `USE_*`、`GITLAB_TOOL_PROFILE` 都不会)。设置 `GITLAB_ALLOWED_PROJECT_IDS` 或会话项目范围后,只接受允许项目的 `/projects/:id` 路径。`/search`、`/users`、`/groups/:id`、`/runners` 等端点会被拒绝。请求体和查询参数中指向其他项目的值不会被检查。`GITLAB_PROJECT_ID` 和 OAuth 群组允许列表不会被此工具强制执行。
216
216
 
217
217
  - sse
218
218
 
@@ -96,9 +96,13 @@ function assertRedirectedApiPathAllowed(apiBaseUrl, allowlist, target, trustedAl
96
96
  if (allowlist.length === 0) {
97
97
  return;
98
98
  }
99
- if (relative === undefined || relative.length === 0) {
99
+ // Only an untrusted cross-origin hop is left here, and it carries no credentials.
100
+ if (relative === undefined) {
100
101
  return;
101
102
  }
103
+ if (relative.length === 0) {
104
+ throw notProjectScopedError(allowlist);
105
+ }
102
106
  let normalized;
103
107
  try {
104
108
  normalized = normalizeGitLabApiRelativePath(relative);
@@ -109,6 +113,15 @@ function assertRedirectedApiPathAllowed(apiBaseUrl, allowlist, target, trustedAl
109
113
  }
110
114
  assertProjectAllowlist(normalized, allowlist);
111
115
  }
116
+ function notProjectScopedError(allowlist) {
117
+ return new GitLabApiRequestInputError(`Access denied: gitlab_api_request path is not scoped to a project in the allowed project list: ${allowlist.join(", ")}. ` +
118
+ "Only /projects/:id and /projects/:id/... paths are allowed while a project allowlist is in effect");
119
+ }
120
+ /**
121
+ * With an allowlist, the path must be `projects/:id` or `projects/:id/...` for an
122
+ * allowed project. Any other path (groups, users, search, admin, the projects
123
+ * collection, or a route this parser does not recognize) is refused.
124
+ */
112
125
  function assertProjectAllowlist(relativePath, allowlist) {
113
126
  if (allowlist.length === 0) {
114
127
  return;
@@ -122,7 +135,7 @@ function assertProjectAllowlist(relativePath, allowlist) {
122
135
  throw new GitLabApiRequestInputError(message);
123
136
  }
124
137
  if (projectId === undefined) {
125
- return;
138
+ throw notProjectScopedError(allowlist);
126
139
  }
127
140
  const rawSegment = relativePath.split("/")[1] ?? projectId;
128
141
  if (!projectAllowed(projectId, rawSegment, allowlist)) {
@@ -38,7 +38,7 @@ const TOOL_GUIDANCE = {
38
38
  delete_issue_link: "Use this to remove an existing relationship between two issues; use `list_issue_links` or `get_issue_link` to verify the link first. The operation changes issue relationships, requires issue-edit permission, and returns the result or an error when the link is missing or access is denied.",
39
39
  download_job_artifacts: "Use this to retrieve a pipeline job's artifact archive; remote HTTP mode returns a download URL while local mode saves the archive to a local path. It is read-only on GitLab but creates a local file in stdio mode (rejected in readonly mode), requires job/project access, and returns the download result or an artifact/permission error.",
40
40
  download_attachment: "Use this to retrieve a previously uploaded project attachment; remote mode returns inline base64 for images or a download URL, while local mode saves the file as a new file under the download directory (GITLAB_DOWNLOAD_DIR, default .gitlab-mcp-downloads). It is read-only with respect to GitLab but creates a local file in stdio mode (readonly mode returns images inline and rejects everything else), never replaces an existing file, requires project access, and returns the file content or an attachment/permission error.",
41
- gitlab_api_request: "Send one GitLab REST call under /api/v4. Readonly mode allows GET only, and modify mode rejects DELETE. Enable it only by listing api in GITLAB_TOOLSETS; all, discover_tools, and GITLAB_TOOLS do not. Prompt injection can drive this tool, so operators who rely on group, project, or tool restrictions must not enable it. GITLAB_ALLOWED_PROJECT_IDS is enforced only for /projects/:id paths; other endpoints are not constrained.",
41
+ gitlab_api_request: "Send one GitLab REST call under /api/v4. Readonly mode allows GET only, and modify mode rejects DELETE. Enable it only by listing api in GITLAB_TOOLSETS; all, discover_tools, and GITLAB_TOOLS do not. Prompt injection can drive this tool, so operators who rely on group, project, or tool restrictions must not enable it. With GITLAB_ALLOWED_PROJECT_IDS or a session project scope, only /projects/:id paths for an allowed project are accepted and every other path is rejected; body and query parameters that name another project are not checked.",
42
42
  execute_graphql: "Use this only when a supported GitLab REST tool does not cover the requested operation; prefer a typed tool when one exists. The query is sent directly to GitLab and can include mutations when permission allows, so callers must treat it as potentially state-changing and handle GraphQL errors in the returned response.",
43
43
  discover_tools: "Use this when a needed opt-in category is not currently exposed; omit `category` to inspect available categories, then call it with a category to activate that group for the current session. It changes only the session's tool registry, returns the active-tool summary, and does not change GitLab data.",
44
44
  health_check: "Use this to verify server connectivity and authentication before making GitLab requests; use `whoami` when the authenticated user's identity is the goal. A 403 from GET /user with an insufficient_scope error means the token is accepted but User API scope is missing (read_user or fine-grained User:Read); the check stays ok, sets user_api_warning, and omits version metadata. Rate-limit and authentication-ban 403 responses stay unauthenticated. It does not mutate GitLab state and returns server/authentication status plus GitLab version details when available. Connection failures with no HTTP response return status error, authenticated false, and an error object (kind tls, dns, timeout, or network, plus code and message) instead of a protocol error.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zereight/mcp-gitlab",
3
- "version": "2.3.7-next.138",
3
+ "version": "2.3.7-next.139",
4
4
  "mcpName": "io.github.zereight/gitlab-mcp",
5
5
  "description": "GitLab MCP server for projects, merge requests, issues, pipelines, wiki, releases, and more",
6
6
  "keywords": [