Back to skill

Security audit

Minimax Monitor

Security checks for vulnerabilities and agentic risk

Overview

This is a real MiniMax quota dashboard, but its code can use the local API key and expose billable actions more broadly than its documentation promises.

Review before installing. This skill needs access to your MiniMax API key and will make authenticated MiniMax requests. Do not run it on a shared or network-exposed machine, do not rely on --no-probe to block billable probe calls, and assume the dashboard may read and use ~/.mmx/config.json as soon as the page polls quota, not only after the documented credential button is clicked.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
mmx-monitor-server.js:369
Finding

API key is read and used before explicit user authorization

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
mmx-monitor-server.js:545
Finding

Local credential proxy is not restricted to loopback and uses spoofable request headers as access controls

Content
View full analysis
{ console.log(`MiniMax Monitor API -> http://localhost:${PORT}`); ``` The CORS check treats requests without an `Origin` header as acceptable non-CORS requests: ```js function corsOriginFor(req) { const origin = req.headers['origin'] || ''; // 同源请求(curl / 本机直连)通常不带 Origin header,直接返回 false 表示无需 CORS 头 if (!origin) return false; if (ALLOWED_ORIGINS.includes(origin)) return origin; // 不在白名单:返回 null(不允许跨源) return null; } ``` The quota endpoint has no independent origin, session, or user-authorization check: ```js if (req.method === 'GET' && urlPath === '/api/token_plan') { if (requireKeyOrFail(res)) return; try { const key = apiKey; const raw = await httpsGet( 'https://www.minimaxi.com/v1/token_plan/remains', { 'Authorization': 'Bearer ' + key, 'Content-Type': 'application/json' } ); ``` The probe endpoint relies on a client-controlled `Referer` value: ```js const referer = req.headers['referer'] || ''; if (!referer || !ALLOWED_ORIGINS.some(o => o !== 'null' && referer.startsWith(o))) { res.writeHead(403, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ ok: false, error: 'probe requires Referer from local origin (e.g. http://127.0.0.1:9877/)' })); return; } ``` ### Technical Analysis Calling `server.listen(PORT)` without an explicit host commonly binds Node.js to an unspecified address such as `::` or `0.0.0.0`, rather than guaranteeing a loopback-only listener. The application logs a localhost URL, but the code does not enforce that network boundary. CORS is a browser response policy, not server-side a ...[truncated 1930 chars]
Remediation
View remediation
{ // ... }); ``` 2. Consider a separate explicit IPv6 loopback listener only if required. 3. Generate a cryptographically random session token at startup or after confirmed credential authorization. 4. Require the token on all `/api/*` endpoints, including `/api/token_plan`, `/api/probe`, and `/api/history`. 5. Use `Origin` and `Referer` only as defense-in-depth, not as authentication. 6. Parse request origins with `new URL()` and compare exact protocol, hostname, and port values. Do not use string-prefix matching. 7. Reject unexpected `Host` headers to reduce DNS-rebinding exposure. 8. Add rate limits and request serialization to quota-consuming endpoints. 9. Prefer `POST` for the probe operation because it has side effects, and require an anti-CSRF token. 10. Add integration tests from non-loopback interfaces and direct HTTP clients without browser CORS enforcement. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
mmx-monitor-server.js:10
Finding

Documented --no-probe security option is not implemented

Content
View full analysis
o !== 'null' && referer.startsWith(o))) { res.writeHead(403, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ ok: false, error: 'probe requires Referer from local origin (e.g. http://127.0.0.1:9877/)' })); return; } const [probeResult, burstResult, ordinaryResult] = await Promise.all([ probeApiLatency(apiKey), probeBurstApi(apiKey), probeOrdinaryApi(apiKey), ]); ``` The documentation advertises the following option: ```bash node mmx-monitor-server.js --no-probe ``` ### Technical Analysis `SKILL.md` and both README variants state that `--no-probe` completely disables the inference-probe endpoint. The implementation never checks for `--no-probe`, and the `/api/probe` route is always registered and executable. This creates a false security boundary. A user may intentionally select the option to guarantee that no inference calls can occur, yet the service still accepts probe requests and can issue five MiniMax completion requests. The existing UI confirmation is not an endpoint-level control. A direct client can bypass the UI, and the `Referer` check can be forged by non-browser c ...[truncated 998 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
mmx-monitor-server.js:173
Finding

Upstream-controlled model names are rendered through innerHTML without escaping

Content
View full analysis
'; html+='
'+(intervalDisabled?m.name:'通用额度池 (对话/语音/音乐/图像)')+''+(m.window==='4小时'?'5小时':m.window)+'
'; ``` The resulting string is interpreted as markup: ```js grid.innerHTML=html; ``` ### Technical Analysis `e.model_name` originates in the response from `https://www.minimaxi.com/v1/token_plan/remains`. If the value is not found in `MODEL_NAME_MAP`, the server returns it verbatim as `name`. For entries where `interval_unlimited === true`, the browser concatenates `m.name` into an HTML string and assigns the completed string to `grid.innerHTML`. No contextual HTML escaping or model-name validation occurs. If an upstream response, compromised endpoint, proxy, or unexpected backend value contains HTML markup, the browser will interpret it rather than display it as text. A payload using an event handler on an injected element could execute JavaScript in the dashboard origin. ### Attack Path 1. The MiniMax quota response contains an unknown `model_name` carrying HTML markup. 2. `buildModels()` falls back to the unmodified `e.model_name`. 3. `/api/token_plan` returns that value to the browser in JSON. 4. `renderModels()` concatenates the value into the ...[truncated 955 chars]
Remediation
View remediation
`, `"`, `'`, and event-handler payloads, verifying that they appear only as literal text. 7. Review other `innerHTML` assignments and string-built attributes for equivalent untrusted-data paths. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (22)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 88)May include surrounding context.

bash
# Copy template
cp .env.example .env

MINIMAX_API_KEY=sk-cp-…here           # MiniMax API Key (Token Plan type)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README_zh.md (reported line 94)May include surrounding context.

bash
# Copy template
cp .env.example .env

MINIMAX_API_KEY=sk-cp-…here           # MiniMax API Key (Token Plan type)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 152)May include surrounding context.

md
- ✅ `<skill-dir>/history.jsonl` is created on first `token_plan` poll and is mentioned in `SKILL.md` Security section + this file.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 153)May include surrounding context.

md
- ✅ `<skill-dir>/history.jsonl` is created on first `token_plan` poll and is mentioned in `SKILL.md` Security section + this file.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 154)May include surrounding context.

md
- ✅ `<skill-dir>/history.jsonl` is created on first `token_plan` poll and is mentioned in `SKILL.md` Security section + this file.

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'env' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

This markdown file contains natural-language product/skill descriptions, and L074 states the trigger was narrowed to a single Chinese phrase (mmx 仪表盘启动). Elsewhere the changelog also describes user-facing buttons and labels only in Chinese, but this file does not indicate that the skill is intentionally China/Chinese-locale-only or that users can choose language, which can violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 101)May include surrounding context.

md
1. **Load local credentials on demand, never cached** — Dashboard's "加载本地凭证" button triggers `POST /api/load_cred` which authorizes the server to read `~/.mmx/config.json` fresh on every credentialed request (v1.7.0+). The key is never held in process memory between calls — verified by `lldb memory find` showing no key in the server process. Not returned in any HTTP response.
2. **Poll MiniMax API every 60s** — `https://www.minimaxi.com/v1/token_plan/remains` for quota data.
3. **Write local usage samples** — `<skill-dir>/history.jsonl` is appended on each quota poll (24h ring buffer, contains usage percentages only, no credentials).
4. **Run inference probe on user demand only** — Dashboard button + `confirm()` triggers `/api/probe` (5 chat completion requests, ~180 tokens).

**This service will NOT**:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · mmx-monitor-server.js (reported line 206)May include surrounding context.

js
const t0 = Date.now();
  try {
    const { status, data } = await httpsGet(
      'https://api.minimaxi.com/v1/text/chatcompletion_v2',
      {
        'Authorization': 'Bearer ' + key,
        'Content-Type': 'application/json',

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · mmx-monitor-server.js (reported line 236)May include surrounding context.

js
const t0 = Date.now();
  try {
    const { status, data } = await httpsGet(
      'https://api.minimaxi.com/v1/text/chatcompletion_v2',
      {
        'Authorization': 'Bearer ' + key,
        'Content-Type': 'application/json',

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · mmx-monitor-server.js (reported line 270)May include surrounding context.

js
const t0 = Date.now();
  try {
    const { status, data } = await httpsGet(
      'https://api.minimaxi.com/v1/text/chatcompletion_v2',
      {
        'Authorization': 'Bearer ' + key,
        'Content-Type': 'application/json',

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The comments assert the key is not kept in process memory, but manual input is assigned to the apiKey variable and retained in page memory. While this is not an immediate exfiltration primitive in the provided file, misleading security claims around secret handling can cause unsafe operator assumptions and increase exposure if any other script, extension, crash dump, or debugging path can inspect page state.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The comment at L350 states '启动时不读 config.json,不读 localStorage。直接 startMon。' in a way that suggests a harmless startup path, but startMon at L351 immediately calls fetchQuota, which attempts backend quota access on load. This is an intent/documentation mismatch because the inline documentation frames startup as only avoiding local reads, while the actual code initiates monitoring network activity right away.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The instruction "Keep SKILL.md body in English" is a natural-language locale requirement. Under the policy, forcing a specific language without opt-in or a clear documented justification is a reportable violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The line "SKILL.md body must be in English; reference docs in English" mandates a specific language for documentation. This is a locale/language policy issue because it does not offer contributor choice or explain a necessary region- or compliance-based reason.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The main README is written in English, but it instructs users to click a button labeled only as "加载本地凭证" without an English equivalent or any opt-in language selection in the instruction itself. This can be viewed as a locale/language policy issue because the skill's operational guidance assumes a specific language for a required UI interaction rather than offering a user-selectable language path.

Content

No source excerpt is available for this finding.

Lp4

Low
Category
MCP Least Privilege
Confidence
65% confidence
Finding

Declared permissions with no matching code capability may indicate removed functionality or pre-staging for future abuse.

Content

No source excerpt is available for this finding.

Lp4

Low
Category
MCP Least Privilege
Confidence
65% confidence
Finding

Declared permissions with no matching code capability may indicate removed functionality or pre-staging for future abuse.

Content

No source excerpt is available for this finding.

Lp4

Low
Category
MCP Least Privilege
Confidence
65% confidence
Finding

Declared permissions with no matching code capability may indicate removed functionality or pre-staging for future abuse.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The markdown explicitly presents the trigger word as mmx 仪表盘启动, which is a Chinese-only invocation example, and the document does not state that users may choose their preferred language for interacting with the skill. While other example phrases appear earlier in the frontmatter, the main user-facing trigger section emphasizes a single locale-specific phrase without opt-in or language-choice guidance.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document declares lang="zh-CN", and the UI text and time formatting are consistently hard-coded for Chinese. This imposes a specific language/locale on users without offering an opt-in or language selection, which matches the natural-language locale policy violation criteria.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.