Skip to content

Commit a06dcb9

Browse files
committed
fix: harden input handling in api client, mcp config, and yaml escape
- use null check instead of truthy for limit param (fixes limit=0 bug) - encode url path segments to prevent path injection - fix mcp config read/write key mismatch when both servers and mcpServers exist - escape backslashes and newlines in yaml frontmatter Constraint: all fixes are at API/output boundaries, no internal logic changes Confidence: high Scope-risk: narrow
1 parent 1ca761d commit a06dcb9

File tree

3 files changed

+6
-7
lines changed

3 files changed

+6
-7
lines changed

src/api/client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,12 @@ export class YavyApiClient {
149149
async search(query: string, options?: { project?: string; limit?: number }): Promise<SearchResponse> {
150150
const params = new URLSearchParams({ query });
151151
if (options?.project) params.set('project', options.project);
152-
if (options?.limit) params.set('limit', String(options.limit));
152+
if (options?.limit != null) params.set('limit', String(options.limit));
153153
return this.request<SearchResponse>('GET', `/search?${params}`);
154154
}
155155

156156
async downloadSkill(orgSlug: string, projectSlug: string): Promise<ArrayBuffer> {
157-
const url = `${YAVY_BASE_URL}/api/v1/${orgSlug}/${projectSlug}/skill/download`;
157+
const url = `${YAVY_BASE_URL}/api/v1/${encodeURIComponent(orgSlug)}/${encodeURIComponent(projectSlug)}/skill/download`;
158158

159159
const response = await this.fetchWithRetry(url, {
160160
method: 'GET',

src/commands/init/configure-tool.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ function buildMcpUrl(projects: ApiProject[]): string {
5656
);
5757
}
5858

59-
return `${YAVY_BASE_URL}/mcp/${orgSlugs[0]}`;
59+
return `${YAVY_BASE_URL}/mcp/${encodeURIComponent(orgSlugs[0])}`;
6060
}
6161

6262
function readJsonFile(configPath: string): Record<string, unknown> {
@@ -80,11 +80,10 @@ function writeJsonFile(configPath: string, data: Record<string, unknown>): void
8080
/** Standard MCP config: { servers: { yavy: { url, type } } } (Cursor, VS Code) */
8181
function mergeJsonMcpConfig(configPath: string, projects: ApiProject[]): void {
8282
const existing = readJsonFile(configPath);
83-
const servers = (existing.servers ?? existing.mcpServers ?? {}) as Record<string, unknown>;
83+
const serverKey = existing.mcpServers ? 'mcpServers' : 'servers';
84+
const servers = (existing[serverKey] ?? {}) as Record<string, unknown>;
8485

8586
servers['yavy'] = { url: buildMcpUrl(projects), type: 'sse' };
86-
87-
const serverKey = existing.mcpServers ? 'mcpServers' : 'servers';
8887
existing[serverKey] = servers;
8988
writeJsonFile(configPath, existing);
9089
}

src/commands/init/generate-skill.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,5 +150,5 @@ function escapePipe(str: string): string {
150150
}
151151

152152
function escapeYaml(str: string): string {
153-
return str.replace(/"/g, '\\"');
153+
return str.replace(/\\/g, '\\\\').replace(/\n/g, ' ').replace(/\r/g, '').replace(/"/g, '\\"');
154154
}

0 commit comments

Comments
 (0)