Back to skill

Security audit

ai-diabetes-coach

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent local diabetes-coach API, but it handles sensitive health data and insulin-dose guidance with documentation and dependency issues that warrant careful review before installation.

Install only for local, single-user testing unless you first remove the npm flask dependency, pin Python dependencies, resolve the authentication documentation conflict, add request size/rate/record limits, and ensure medical outputs are reviewed by a qualified clinician. Do not expose it directly to the internet or use it as a production multi-user health service as packaged.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (3)

T08 · Insecure Dependencies

Warning
Location
package.json:7
Finding

Unrelated and Unbounded npm Dependency Creates Supply-Chain Exposure

Content
View full analysis

Vulnerability Details

File Location: package.json:7-13
Vulnerability Type: Dependency confusion and unnecessary package installation
Risk Level: Medium

Vulnerable Code

json
"scripts": {
  "start": "python app.py"
},
"dependencies": {
  "flask": ">=2.0"
},
"keywords": [

Technical Analysis

The application is implemented in Python and imports the Python Flask framework. However, package.json declares an npm package named flask. npm and PyPI are separate package ecosystems, so the npm dependency does not provide the Python module used by app.py.

Consequently, an installation process that automatically executes npm install will retrieve and process an unrelated package that is not necessary for the declared functionality. The range >=2.0 is also unbounded, allowing future package versions to be selected without review. This unnecessarily expands the project’s supply-chain attack surface.

The audit did not establish that the referenced npm package is currently malicious. The vulnerability is the unnecessary and misleading dependency declaration and the resulting exposure to unrelated package content and lifecycle behavior.

Attack Path

  1. A deployment pipeline or developer identifies package.json and automatically runs npm install.
  2. npm resolves flask from the npm registry rather than installing the Python Flask framework.
  3. npm downloads an unrelated package and any transitive dependencies permitted by the unbounded version range.
  4. Package installation or lifecycle behavior is processed in the build environment.
  5. If the unrelated package or a future permitted release is compromised, the build environment and its accessible credentials or artifacts may be affected.

Impact Assessment

This does not directly grant application privileges based on the reviewed source alone. Its scope is the environment in which npm installation occurs. A compromised ...[truncated 337 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove package.json if npm is not genuinely required by the project.
  2. At minimum, remove the npm flask dependency and avoid running npm install for this service.
  3. Manage Python Flask exclusively through Python dependency tooling.
  4. Pin reviewed Python package versions and generate a lockfile or hash-verified requirements file.
  5. Configure CI/CD to install only dependencies required by the application.
  6. Add dependency provenance and vulnerability scanning to the build process.

T09 · Insecure Skill Coding Practices

Warning
Location
app.py:50
Finding

Unbounded In-Memory Health Record Storage Enables Authenticated Denial of Service

Content
View full analysis

Vulnerability Details

File Location: app.py:50-62
Vulnerability Type: Unbounded resource consumption
Risk Level: Medium

Vulnerable Code

python
@app.route('/record', methods=['POST'])
@require_auth
def record():
    data = request.get_json()
    uid = data.get('user_id', 'default')
    g = safe_float(data.get('glucose'), 0.0)
    _, lvl, _ = glucose_safety(g)
    if lvl == "critical": audit.warning(f"Critical glucose {g} for {uid}")
    rec = {"ts": data.get('timestamp', datetime.now().isoformat()), "g": g,
           "carbs": safe_float(data.get('meal_carbs'), 0, 0, 300),
           "exercise": safe_float(data.get('exercise_minutes'), 0, 0, 240),
           "insulin": safe_float(data.get('insulin_dose'), 0, 0, MAX_BOLUS)}
    user_records.setdefault(uid, []).append(rec)
    return jsonify({"status": "success", "id": len(user_records[uid])-1}), 201

Technical Analysis

Every authenticated request can create a new arbitrary user identifier and append another record to the process-wide user_records dictionary. The implementation imposes no limit on:

  • Request body size
  • User identifier length
  • Number of distinct user identifiers
  • Number of records per user
  • Total records held by the process
  • Retention time for stored records
  • Request frequency

Because all records remain in memory until process termination, an authenticated caller can force monotonically increasing memory consumption. Authentication reduces exposure but does not prevent abuse by a legitimate client, a client with a leaked shared API key, or an accidentally malfunctioning integration.

Attack Path

  1. An attacker obtains or is legitimately issued the shared API key.
  2. The attacker repeatedly sends POST /record requests.
  3. Requests use unique user_id values, or repeatedly append records to one user.
  4. Each accepted request permanently expands the in-memory dictionary or record l ...[truncated 747 chars]
Remediation
View remediation

Remediation Suggestions

  1. Set Flask’s MAX_CONTENT_LENGTH to a small value appropriate for record requests.
  2. Validate user_id against a strict format and enforce a short maximum length.
  3. Enforce per-user and global record limits.
  4. Apply a retention policy and remove records older than the supported reporting period.
  5. Store records in a bounded persistent data store instead of an unrestricted process dictionary.
  6. Add per-key and per-source rate limiting to /record.
  7. Use distinct per-user credentials if the service is extended beyond its documented single-user deployment model.
  8. Apply container or process memory limits and monitor rejected requests, memory growth, and worker restarts.

T09 · Insecure Skill Coding Practices

Note
Location
app.py:56
Finding

Unvalidated Stored Timestamp Causes Persistent Risk-Endpoint Failure

Content
View full analysis

Vulnerability Details

File Location: app.py:56 and core.py:47
Vulnerability Type: Improper input validation and unhandled exception
Risk Level: Low

Vulnerable Code

The record endpoint stores an arbitrary caller-provided timestamp without parsing or validation:

python
rec = {"ts": data.get('timestamp', datetime.now().isoformat()), "g": g,
       "carbs": safe_float(data.get('meal_carbs'), 0, 0, 300),
       "exercise": safe_float(data.get('exercise_minutes'), 0, 0, 240),
       "insulin": safe_float(data.get('insulin_dose'), 0, 0, MAX_BOLUS)}

The risk calculation later assumes every stored timestamp is valid ISO format:

python
recent = [r for r in recs if datetime.fromisoformat(r['ts']) >= datetime.now() - timedelta(days=7)]

Technical Analysis

datetime.fromisoformat() raises ValueError for malformed timestamp strings. Because the input is stored without validation and the parsing operation has no exception handling, one malformed record can cause every subsequent risk-report request for the associated user to fail.

The condition requiring at least three records means an attacker must create at least three records before reaching the vulnerable parsing operation. At least one of those records can contain an invalid timestamp. The corrupted record remains in memory until the process restarts or the data is otherwise cleared.

Attack Path

  1. An attacker obtains or legitimately possesses the shared API key.
  2. The attacker submits at least three records for a chosen user identifier.
  3. At least one record contains a malformed value such as "timestamp": "not-a-date".
  4. The attacker or another caller requests /risk/{uid} for that user.
  5. datetime.fromisoformat() raises an uncaught ValueError.
  6. The endpoint returns an internal server error.
  7. Repeated risk requests continue to fail while the malformed record remains in process memory.

Impact

...[truncated 420 chars]

Remediation
View remediation

Remediation Suggestions

  1. Parse and validate timestamps before storing records.
  2. Reject malformed timestamps with HTTP 400 and a clear error message.
  3. Normalize accepted values to one canonical timezone-aware ISO 8601 representation.
  4. Define whether naive timestamps are allowed and consistently enforce that policy.
  5. Add defensive exception handling in Coach.risk() so one legacy malformed record cannot terminate the entire report.
  6. Log invalid stored records without including unnecessary health information.
  7. Add tests covering malformed strings, missing timestamps, timezone offsets, extreme dates, and mixed naive and timezone-aware values.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (14)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This markdown file presents all user-facing instructions, endpoint descriptions, and warnings exclusively in Chinese. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale limitation is explicitly justified, which is not stated here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This markdown file presents all operational instructions in Chinese, which effectively forces a specific language on users. The policy allows locale constraints only when the skill offers user choice or clearly documents a justified regional restriction, neither of which appears here.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest description and the full user-facing documentation are written in Chinese, and the file does not indicate that users may choose another language. This can violate language/locale policy requirements when a skill effectively forces a specific language without documented opt-in or justification.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation makes contradictory security claims: it says the API key is mandatory and the service refuses to start without it, but later says API-key authentication is optional in production. In a medical-advice service that includes insulin dose calculation, this ambiguity can lead operators to deploy without authentication, exposing sensitive health endpoints and allowing unauthorized requests to generate or manipulate medical guidance.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The guide makes a strong security claim that API authentication is mandatory and that the service will refuse to start without API_KEY, but the documentation shown does not demonstrate or prove that this enforcement actually exists. In a health-data service, overstated security guarantees can cause operators to deploy the system assuming access control is enforced when it may not be, leading to exposure of sensitive medical information or unsafe medical-advice endpoints.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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 · USE_GUIDE.md (reported line 49)May include surrounding context.

md
BASE = "http://localhost:5000"

# 1. 设置用户参数(需 X-API-Key header)
requests.post(f"{BASE}/profile", headers={"X-API-Key": "your_key"}, json={
    "user_id": "demo",
    "target_glucose": 6.0,
    "correction_factor": 2.0,

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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 · USE_GUIDE.md (reported line 57)May include surrounding context.

md
})

# 2. 添加记录
requests.post(f"{BASE}/record", headers={"X-API-Key": "your_key"}, json={
    "user_id": "demo",
    "glucose": 8.2,
    "meal_carbs": 50

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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 · USE_GUIDE.md (reported line 64)May include surrounding context.

md
})

# 3. 获取建议
resp = requests.post(f"{BASE}/advice", headers={"X-API-Key": "your_key"}, json={
    "glucose": 8.2,
    "meal_type": "dinner"
})

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module description is in Chinese, and later endpoints return Chinese-only user-facing strings, indicating the skill is designed to operate in a fixed language. The file does not offer user opt-in, language selection, or a documented region-specific justification, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The API returns Chinese-language disclaimer and tips such as at L070 and L091-L100, but there is no mechanism for users to choose their preferred language. This is a natural-language policy issue because the skill imposes a specific locale on all users by default.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The module description explicitly identifies the skill as a Chinese-language diabetes rehabilitation assistant, and all user-facing messages throughout the file are hard-coded in Chinese. There is no indication that the user can opt into another language or that the locale restriction is documented as a justified region-specific limitation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The package description is written entirely in Chinese, which implies a fixed language presentation without indicating that users can choose another language. This can conflict with language/locale policy expectations when a skill is not clearly documented as region-specific or offering opt-in language selection.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: flask has 10 known advisory(ies) (CVE-2025-47278 (Flask uses fallback key instead of current signing key); CVE-2018-1000656 (Flask is vulnerable to Denial of Service via incorrect encoding of JSON data); CVE-2019-1010083 (Pallets Project Flask is vulnerable to Denial of Service via Unexpected memory u) +7 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency specification flask>=2.0,<4.0 is not pinned to a specific patched version, so builds may resolve to Flask releases with known CVEs or vary over time in ways that are hard to audit and reproduce. In a healthcare-related skill that may process sensitive user data, relying on an unpinned web framework increases the risk of deploying a vulnerable version and weakens supply-chain control.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.