Disallow and suppress unsafe assignment (#19736)

This commit is contained in:
Christian Gunderman
2026-02-20 22:28:55 +00:00
committed by GitHub
parent b746524a1b
commit 58d637f919
71 changed files with 149 additions and 22 deletions
+3 -1
View File
@@ -22,6 +22,7 @@ import type {
Prompt,
ReadResourceResult,
Resource,
Tool as McpTool,
} from '@modelcontextprotocol/sdk/types.js';
import {
ListResourcesResultSchema,
@@ -31,7 +32,6 @@ import {
ToolListChangedNotificationSchema,
PromptListChangedNotificationSchema,
ProgressNotificationSchema,
type Tool as McpTool,
} from '@modelcontextprotocol/sdk/types.js';
import { ApprovalMode, PolicyDecision } from '../policy/types.js';
import { parse } from 'shell-quote';
@@ -1996,6 +1996,7 @@ export async function createTransport(
// The `XcodeMcpBridgeFixTransport` wrapper hides the underlying `StdioClientTransport`,
// which exposes `stderr` for debug logging. We need to unwrap it to attach the listener.
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const underlyingTransport =
transport instanceof XcodeMcpBridgeFixTransport
? // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion
@@ -2007,6 +2008,7 @@ export async function createTransport(
underlyingTransport.stderr
) {
underlyingTransport.stderr.on('data', (data) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const stderrStr = data.toString().trim();
debugLogger.debug(
`[DEBUG] [MCP STDERR (${mcpServerName})]: `,
+4
View File
@@ -481,8 +481,10 @@ class GrepToolInvocation extends BaseToolInvocation<
basePath: string,
): GrepMatch | null {
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const json = JSON.parse(line);
if (json.type === 'match' || json.type === 'context') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const data = json.data;
// Defensive check: ensure text properties exist (skips binary/invalid encoding)
if (data.path?.text && data.lines?.text) {
@@ -500,7 +502,9 @@ class GrepToolInvocation extends BaseToolInvocation<
return {
filePath: relativeFilePath || path.basename(absoluteFilePath),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
lineNumber: data.line_number,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
line: data.lines.text.trimEnd(),
isContext: json.type === 'context',
};
+1
View File
@@ -390,6 +390,7 @@ export class ToolRegistry {
// execute discovery command and extract function declarations (w/ or w/o "tool" wrappers)
const functions: FunctionDeclaration[] = [];
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const discoveredItems = JSON.parse(stdout.trim());
if (!discoveredItems || !Array.isArray(discoveredItems)) {
@@ -75,7 +75,7 @@ export class XcodeMcpBridgeFixTransport
// We can cast because we verified 'result' is in response,
// but TS might still be picky if the type is a strict union.
// Let's treat it safely.
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion, @typescript-eslint/no-unsafe-assignment
const result = response.result as any;
// Check if we have content but missing structuredContent
@@ -85,12 +85,15 @@ export class XcodeMcpBridgeFixTransport
result.content.length > 0 &&
!result.structuredContent
) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const firstItem = result.content[0];
if (firstItem.type === 'text' && typeof firstItem.text === 'string') {
try {
// Attempt to parse the text as JSON
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const parsed = JSON.parse(firstItem.text);
// If successful, populate structuredContent
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
result.structuredContent = parsed;
} catch (_) {
// Ignored: Content is likely plain text, not JSON.