fix(executors): inject MiMoCode anti-abuse marker so free endpoint stops 403ing (#3728)

Integrated into release/v3.8.23
This commit is contained in:
Felipe Sartori
2026-06-12 11:54:26 -03:00
committed by GitHub
parent 9d0197634a
commit 635e2363b5
2 changed files with 241 additions and 34 deletions

View File

@@ -28,6 +28,42 @@ const COOLDOWN_MAX_MS = 60_000;
const MIMO_SOURCE = "mimocode-cli-free";
/**
* Anti-abuse gate marker required by the Xiaomi free endpoint.
*
* `/api/free-ai/openai/chat` returns `403 "Illegal access"` unless the request body
* contains a recognized MiMoCode prompt signature as a substring inside a `system`-role
* message (verified empirically — headers, fingerprint, and JWT are not what is checked).
* This is the canonical MiMoCode agent opener the official CLI sends, and it is on the
* upstream allowlist. We inject it as a leading system message so user requests pass the
* gate. The string MUST stay byte-for-byte identical — the check is case-sensitive and
* truncations are rejected.
*/
export const MIMO_SYSTEM_MARKER =
"You are MiMoCode, an interactive CLI tool that helps users with software engineering tasks.";
/**
* Ensure the outgoing body carries the MiMoCode anti-abuse marker in a system message.
* Idempotent: if any system message already contains the marker, the body is returned
* unchanged. Bodies without a `messages` array are left untouched.
*/
function injectSystemMarker(body: Record<string, unknown>): Record<string, unknown> {
const messages = body.messages;
if (!Array.isArray(messages)) return body;
const hasMarker = messages.some(
(m) =>
m != null &&
typeof m === "object" &&
(m as { role?: unknown }).role === "system" &&
typeof (m as { content?: unknown }).content === "string" &&
(m as { content: string }).content.includes(MIMO_SYSTEM_MARKER)
);
if (hasMarker) return body;
return { ...body, messages: [{ role: "system", content: MIMO_SYSTEM_MARKER }, ...messages] };
}
const USER_AGENTS = [
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
@@ -67,7 +103,9 @@ function getCpuModel(): string {
try {
const cpus = os.cpus();
if (cpus.length > 0 && cpus[0].model) return cpus[0].model.trim();
} catch { /* ignore */ }
} catch {
/* ignore */
}
return "unknown-cpu";
}
@@ -80,8 +118,13 @@ export function generateFingerprint(seed?: string): string {
let username = "unknown-user";
try {
username = os.userInfo().username;
} catch { /* ignore */ }
return crypto.createHash("sha256").update(`${hostname}|${platform}|${arch}|${cpu}|${username}`).digest("hex");
} catch {
/* ignore */
}
return crypto
.createHash("sha256")
.update(`${hostname}|${platform}|${arch}|${cpu}|${username}`)
.digest("hex");
}
// ── Bootstrap ──────────────────────────────────────────────────────────────
@@ -91,7 +134,7 @@ const bootstrapInflight = new Map<string, Promise<{ jwt: string; expiresAt: numb
async function bootstrapJwt(
baseUrl: string,
fingerprint: string,
signal?: AbortSignal | null,
signal?: AbortSignal | null
): Promise<{ jwt: string; expiresAt: number }> {
const existing = bootstrapInflight.get(fingerprint);
if (existing) return existing;
@@ -146,7 +189,13 @@ export class MimocodeExecutor extends BaseExecutor {
constructor() {
super("mimocode", { format: "openai" });
this.baseUrl = this.getBaseUrls()[0] || "https://api.xiaomimimo.com";
this.accounts.push({ fingerprint: generateFingerprint(), jwt: "", expiresAt: 0, cooldownUntil: 0, consecutiveFails: 0 });
this.accounts.push({
fingerprint: generateFingerprint(),
jwt: "",
expiresAt: 0,
cooldownUntil: 0,
consecutiveFails: 0,
});
}
private syncAccountsFromCredentials(credentials: ProviderCredentials): void {
@@ -155,13 +204,22 @@ export class MimocodeExecutor extends BaseExecutor {
const existing = new Set(this.accounts.map((a) => a.fingerprint));
for (const fp of fingerprints) {
if (typeof fp === "string" && !existing.has(fp)) {
this.accounts.push({ fingerprint: fp, jwt: "", expiresAt: 0, cooldownUntil: 0, consecutiveFails: 0 });
this.accounts.push({
fingerprint: fp,
jwt: "",
expiresAt: 0,
cooldownUntil: 0,
consecutiveFails: 0,
});
existing.add(fp);
}
}
}
private async getJwtForAccount(account: AccountState, signal?: AbortSignal | null): Promise<string> {
private async getJwtForAccount(
account: AccountState,
signal?: AbortSignal | null
): Promise<string> {
if (isAccountReady(account)) return account.jwt;
const result = await bootstrapJwt(this.baseUrl, account.fingerprint, signal);
account.jwt = result.jwt;
@@ -185,7 +243,10 @@ export class MimocodeExecutor extends BaseExecutor {
private markCooldown(account: AccountState): void {
account.consecutiveFails++;
const backoff = Math.min(COOLDOWN_BASE_MS * Math.pow(2, account.consecutiveFails - 1), COOLDOWN_MAX_MS);
const backoff = Math.min(
COOLDOWN_BASE_MS * Math.pow(2, account.consecutiveFails - 1),
COOLDOWN_MAX_MS
);
account.cooldownUntil = Date.now() + backoff + Math.random() * 1000;
}
@@ -193,7 +254,12 @@ export class MimocodeExecutor extends BaseExecutor {
account.consecutiveFails = 0;
}
buildUrl(_model: string, _stream: boolean, _urlIndex = 0, _credentials?: ProviderCredentials | null): string {
buildUrl(
_model: string,
_stream: boolean,
_urlIndex = 0,
_credentials?: ProviderCredentials | null
): string {
return `${this.baseUrl.replace(/\/$/, "")}${CHAT_PATH}`;
}
@@ -201,7 +267,7 @@ export class MimocodeExecutor extends BaseExecutor {
_credentials: ProviderCredentials,
stream = true,
_clientHeaders?: Record<string, string> | null,
_model?: string,
_model?: string
): Record<string, string> {
const headers: Record<string, string> = {
"Content-Type": "application/json",
@@ -212,9 +278,15 @@ export class MimocodeExecutor extends BaseExecutor {
return headers;
}
transformRequest(model: string, body: unknown, _stream: boolean, _credentials?: ProviderCredentials | null): unknown {
transformRequest(
model: string,
body: unknown,
_stream: boolean,
_credentials?: ProviderCredentials | null
): unknown {
if (typeof body === "object" && body !== null) {
return { ...(body as Record<string, unknown>), model: rewriteModelName(model) };
const withModel = { ...(body as Record<string, unknown>), model: rewriteModelName(model) };
return injectSystemMarker(withModel);
}
return body;
}
@@ -222,15 +294,25 @@ export class MimocodeExecutor extends BaseExecutor {
async testConnection(
_credentials: ProviderCredentials,
_signal?: AbortSignal | null,
log?: ExecuteInput["log"],
log?: ExecuteInput["log"]
): Promise<boolean> {
try {
const account = this.accounts[0];
const jwt = await this.getJwtForAccount(account, _signal);
const resp = await fetch(this.buildUrl("mimo-auto", false), {
method: "POST",
headers: { "Content-Type": "application/json", Authorization: `Bearer ${jwt}`, "X-Mimo-Source": MIMO_SOURCE },
body: JSON.stringify({ model: "mimo-auto", messages: [{ role: "user", content: "ping" }], stream: false }),
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${jwt}`,
"X-Mimo-Source": MIMO_SOURCE,
},
body: JSON.stringify(
injectSystemMarker({
model: "mimo-auto",
messages: [{ role: "user", content: "ping" }],
stream: false,
})
),
signal: _signal ?? undefined,
});
return resp.status === 200;
@@ -251,9 +333,14 @@ export class MimocodeExecutor extends BaseExecutor {
if (signal?.aborted) {
return {
response: new Response(encoder.encode(JSON.stringify({
error: { message: "Request aborted", type: "abort", code: "ABORTED" },
})), { status: 499, headers: { "Content-Type": "application/json" } }),
response: new Response(
encoder.encode(
JSON.stringify({
error: { message: "Request aborted", type: "abort", code: "ABORTED" },
})
),
{ status: 499, headers: { "Content-Type": "application/json" } }
),
url: this.buildUrl(model, stream),
headers: this.buildHeaders(input.credentials, stream),
transformedBody: body,
@@ -282,45 +369,81 @@ export class MimocodeExecutor extends BaseExecutor {
// On auth failure, re-bootstrap this account and retry once
if (resp.status === 401 || resp.status === 403) {
log?.warn?.("MIMOCODE", `Auth failed (${resp.status}) on account ${account.fingerprint.slice(0, 8)}`);
log?.warn?.(
"MIMOCODE",
`Auth failed (${resp.status}) on account ${account.fingerprint.slice(0, 8)}`
);
account.jwt = "";
account.expiresAt = 0;
account.consecutiveFails = 0;
const freshJwt = await this.getJwtForAccount(account, signal);
headers["Authorization"] = `Bearer ${freshJwt}`;
resp = await fetch(url, { method: "POST", headers, body: JSON.stringify(reqBody), signal: signal ?? undefined });
resp = await fetch(url, {
method: "POST",
headers,
body: JSON.stringify(reqBody),
signal: signal ?? undefined,
});
}
if (resp.status === 429) {
this.markCooldown(account);
log?.warn?.("MIMOCODE", `Rate limited on account ${account.fingerprint.slice(0, 8)}, trying next…`);
log?.warn?.(
"MIMOCODE",
`Rate limited on account ${account.fingerprint.slice(0, 8)}, trying next…`
);
continue;
}
this.markSuccess(account);
const respHeaders: Record<string, string> = {};
resp.headers.forEach((v, k) => { respHeaders[k] = v; });
return { response: resp as unknown as Response, url, headers: respHeaders, transformedBody: reqBody };
resp.headers.forEach((v, k) => {
respHeaders[k] = v;
});
return {
response: resp as unknown as Response,
url,
headers: respHeaders,
transformedBody: reqBody,
};
} catch (err) {
this.markCooldown(account);
if (attempt === this.accounts.length - 1) {
const msg = err instanceof Error ? err.message : String(err);
log?.error?.("MIMOCODE", `Executor error: ${msg}`);
return {
response: new Response(encoder.encode(JSON.stringify({
error: { message: msg, type: "upstream_error", code: "EXECUTOR_ERROR" },
})), { status: 502, headers: { "Content-Type": "application/json" } }),
url, headers: this.buildHeaders(input.credentials, stream), transformedBody: body,
response: new Response(
encoder.encode(
JSON.stringify({
error: { message: msg, type: "upstream_error", code: "EXECUTOR_ERROR" },
})
),
{ status: 502, headers: { "Content-Type": "application/json" } }
),
url,
headers: this.buildHeaders(input.credentials, stream),
transformedBody: body,
};
}
}
}
return {
response: new Response(encoder.encode(JSON.stringify({
error: { message: "All accounts exhausted", type: "upstream_error", code: "NO_ACCOUNTS" },
})), { status: 502, headers: { "Content-Type": "application/json" } }),
url, headers: this.buildHeaders(input.credentials, stream), transformedBody: body,
response: new Response(
encoder.encode(
JSON.stringify({
error: {
message: "All accounts exhausted",
type: "upstream_error",
code: "NO_ACCOUNTS",
},
})
),
{ status: 502, headers: { "Content-Type": "application/json" } }
),
url,
headers: this.buildHeaders(input.credentials, stream),
transformedBody: body,
};
}
}

View File

@@ -1,6 +1,10 @@
import { describe, it } from "node:test";
import assert from "node:assert";
import { MimocodeExecutor, generateFingerprint } from "../../open-sse/executors/mimocode.ts";
import {
MimocodeExecutor,
generateFingerprint,
MIMO_SYSTEM_MARKER,
} from "../../open-sse/executors/mimocode.ts";
const executor = new MimocodeExecutor();
@@ -48,7 +52,7 @@ describe("MimocodeExecutor", () => {
const result = (executor as any).transformRequest(
"mcode/mimo-auto",
{ model: "mcode/mimo-auto", messages: [{ role: "user", content: "hi" }] },
false,
false
);
assert.strictEqual(result.model, "mimo-auto");
});
@@ -57,11 +61,91 @@ describe("MimocodeExecutor", () => {
const result = (executor as any).transformRequest(
"mimo-auto",
{ model: "mimo-auto", messages: [{ role: "user", content: "hi" }] },
false,
false
);
assert.strictEqual(result.model, "mimo-auto");
});
// The Xiaomi free endpoint rejects requests with `403 "Illegal access"` unless the
// body contains a recognized MiMoCode prompt signature inside a `system`-role message.
// The executor must inject that marker so user requests pass the upstream anti-abuse gate.
it("transformRequest injects a MiMoCode system marker when none is present", () => {
const result = (executor as any).transformRequest(
"mcode/mimo-auto",
{ model: "mcode/mimo-auto", messages: [{ role: "user", content: "write a haiku" }] },
true
);
assert.ok(Array.isArray(result.messages));
const first = result.messages[0];
assert.strictEqual(first.role, "system");
assert.ok(
typeof first.content === "string" && first.content.includes(MIMO_SYSTEM_MARKER),
"first message must be a system message containing the MiMoCode marker"
);
});
it("transformRequest preserves the original user message after injection", () => {
const result = (executor as any).transformRequest(
"mcode/mimo-auto",
{ model: "mcode/mimo-auto", messages: [{ role: "user", content: "write a haiku" }] },
true
);
const userMsg = result.messages.find((m: any) => m.role === "user");
assert.ok(userMsg);
assert.strictEqual(userMsg.content, "write a haiku");
});
it("transformRequest preserves a caller-provided system prompt alongside the marker", () => {
const result = (executor as any).transformRequest(
"mcode/mimo-auto",
{
model: "mcode/mimo-auto",
messages: [
{ role: "system", content: "You are a pirate." },
{ role: "user", content: "hi" },
],
},
true
);
const systemContents = result.messages
.filter((m: any) => m.role === "system")
.map((m: any) => m.content)
.join("\n");
assert.ok(systemContents.includes(MIMO_SYSTEM_MARKER), "marker present");
assert.ok(systemContents.includes("You are a pirate."), "caller system prompt preserved");
});
it("transformRequest does not duplicate the marker when already present", () => {
const result = (executor as any).transformRequest(
"mcode/mimo-auto",
{
model: "mcode/mimo-auto",
messages: [
{ role: "system", content: `${MIMO_SYSTEM_MARKER}\nExtra context.` },
{ role: "user", content: "hi" },
],
},
true
);
const count = result.messages.filter(
(m: any) =>
m.role === "system" &&
typeof m.content === "string" &&
m.content.includes(MIMO_SYSTEM_MARKER)
).length;
assert.strictEqual(count, 1, "marker should not be duplicated");
});
it("transformRequest leaves a body without a messages array untouched", () => {
const result = (executor as any).transformRequest(
"mcode/mimo-auto",
{ model: "mcode/mimo-auto", prompt: "legacy" },
true
);
assert.strictEqual((result as any).messages, undefined);
assert.strictEqual((result as any).model, "mimo-auto");
});
it("returns 499 on pre-aborted signal", async () => {
const controller = new AbortController();
controller.abort(new Error("cancelled"));