Back to skill

Security audit

Heartflow Minimal2

Security checks for vulnerabilities and agentic risk

Overview

This skill is a cognitive engine with disclosed memory features, but it enables persistent plaintext conversation storage and broad dispatchable write behavior without clear user control.

Review this carefully before installing in any environment where prompts may contain private data, credentials, source code, or business information. Treat memory as default-on local plaintext logging unless you explicitly disable it, and avoid exposing heartflow_dispatch to untrusted callers until persistence routes are constrained.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (4)

T02 · Agent Memory Poisoning

Error
Location
heartflow.js:5078
Finding

Persistent Core-Memory Instruction Poisoning

Content
View full analysis
e.key === rule.key)) { this.memory.addCore(rule.key, rule.value, rule.tags); } } } ``` The method is invoked automatically during startup: ```javascript // ─── [P1 UPGRADE] CORE 层身份规则初始化 ─────────────────────────── this._initCoreRules(); ``` ### Technical Analysis The skill automatically inserts package-author-controlled behavioral rules into the persistent `CORE` memory layer. These are not merely configuration defaults: they direct future agent behavior, including requiring repeated searches and suggesting use of `curl` against named external sites when another search tool fails. The rules are installed during every engine startup if their keys do not already exist. The projec ...[truncated 2461 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
heartflow.js:1859
Finding

Full User Inputs Are Persisted in Plaintext and Enabled by Default

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
heartflow.js:850
Finding

Public Persistence Subsystem Permits Arbitrary Writes to Any Writable Path

Content
View full analysis
wal.append(opType, data), commit: (seq) => wal.commit(seq), replay: () => wal.replay(), flush: () => wal.flush(), atomicWrite: (filePath, content, options) => atomicWrite(filePath, content, options), safeWrite: async (filePath, content) => { const seq = await wal.append('write', { file: filePath, content: content.toString().slice(0, 50000) }); await atomicWrite(filePath, content); await wal.commit(seq); return { ok: true, seq, file: filePath }; }, recover: async () => { const pending = await wal.replay(); const results = []; for (const entry of pending) { try { if (entry.data?.file && entry.data?.content) { await atomicWrite(entry.data.file, entry.data.content); _boundedPush(results, { seq: entry.seq, file: entry.data.file, recovered: true }); } } catch (e) { _boundedPush(results, { seq: entry.seq, file: entry.data?.file, recovered: false, error: e.message }); } } return results; }, getStats: () => ({ type: 'wal+atomic', walDir, opTypes: OP_TYPES }), }; } catch (e) { _boundedPush(this._initErrors, { module: 'persistence', error: e.message }, MAX_HISTORY_SIZE); } ``` The persistence subsystem is included in the ...[truncated 2386 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
heartflow.js:198
Finding

Security Verification Components Fail Open When Modules Cannot Be Loaded

Content
View full analysis
{ try { return require('../verifier/quality-verifier.js'); } catch(e) { return { QualityVerifier: class { constructor() {} verify() { return { passed: true, score: 0, details: '模块加载失败,默认通过' }; } quickVerify() { return { passed: true, score: 0 }; } } }; } }); const _OutputChecker = _lazy('outputChecker', () => { try { return require('../verifier/output-checker.js'); } catch(e) { return { OutputChecker: class { constructor() {} check() { return { valid: true, issues: [], reason: '模块加载失败,默认通过' }; } addChecker() { return this; } } }; } }); ``` ### Technical Analysis When either verifier module fails to load, the replacement implementation reports successful validation: - `verify()` returns `passed: true`. - `quickVerify()` returns `passed: true`. - `check()` returns `valid: true`. This makes module absence, packaging errors, dependency failures, or deliberate module removal indistinguishable from successful verification. The accompanying score of zero does not mitigate callers that rely on the Boolean result. A security or quality gate must fail closed when it cannot evaluate content. Returning success suppresses alerts and allows unchecked output to proceed. ### Attack Path 1. A verifier module is absent, corrupted, incompatible, or prevented from loading. 2. The lazy loader catches the exception. 3. HeartFlow installs a fallback verifier that always approves content. 4. Downstream code receives `passed: true` or `valid: true`. 5. Output that should have been rejected or flagged proceeds without effective verification. An attacker a ...[truncated 594 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (44)

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The documented scope emphasizes cognition and safety constraints, but the analysis suggests undeclared LLM fallback/classification behavior and possible dispatch/query access to dependent subsystems not reflected in permissions. Undisclosed external or subsystem access can expand data flow beyond what reviewers expect, including routing user input into other models or services without clear consent.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The documented scope emphasizes cognition and safety constraints, but the analysis suggests undeclared LLM fallback/classification behavior and possible dispatch/query access to dependent subsystems not reflected in permissions. Undisclosed external or subsystem access can expand data flow beyond what reviewers expect, including routing user input into other models or services without clear consent.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

The documented scope emphasizes cognition and safety constraints, but the analysis suggests undeclared LLM fallback/classification behavior and possible dispatch/query access to dependent subsystems not reflected in permissions. Undisclosed external or subsystem access can expand data flow beyond what reviewers expect, including routing user input into other models or services without clear consent.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The documented scope emphasizes cognition and safety constraints, but the analysis suggests undeclared LLM fallback/classification behavior and possible dispatch/query access to dependent subsystems not reflected in permissions. Undisclosed external or subsystem access can expand data flow beyond what reviewers expect, including routing user input into other models or services without clear consent.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The documented scope emphasizes cognition and safety constraints, but the analysis suggests undeclared LLM fallback/classification behavior and possible dispatch/query access to dependent subsystems not reflected in permissions. Undisclosed external or subsystem access can expand data flow beyond what reviewers expect, including routing user input into other models or services without clear consent.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

The documented scope emphasizes cognition and safety constraints, but the analysis suggests undeclared LLM fallback/classification behavior and possible dispatch/query access to dependent subsystems not reflected in permissions. Undisclosed external or subsystem access can expand data flow beyond what reviewers expect, including routing user input into other models or services without clear consent.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The manifest states memory/local persistence requires explicit authorization, but _checkMemoryEnabled() defaults to enabling memory and prints only informational logs instead of obtaining consent. That means user data is persisted unless the operator proactively disables it, contradicting the stated permission boundary and enabling silent collection of conversation data.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The engine persistently stores full user inputs, self-generated summaries, and restores them across sessions by default, including plain-language content and contextual metadata. This creates long-lived privacy exposure and increases blast radius if the host is compromised, files are backed up externally, or another component reads the local storage.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
88% confidence
Finding

The memory-vault logic explicitly restores inherited context and permanent memories across sessions, and the surrounding rules/descriptions indicate broad retention and reuse of prior user context. In a cognition engine handling intimate or sensitive conversations, this increases the risk of over-collection, unintended profiling, and cross-session privacy leakage beyond user expectations.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The code comments promise AES-256-GCM encrypted dialogue storage, but recordDialogue() writes raw conversation content to memory/dialogue-history.jsonl in plaintext. This creates a confidentiality gap: users and integrators may rely on a false security guarantee while sensitive prompts, outputs, and metadata are stored directly on disk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The manifest advertises capabilities such as code execution, environment-variable access, and optional HTTP service, but it does not declare an explicit tool/permission scope. That creates an authorization ambiguity: hosts and reviewers cannot reliably determine what the skill may invoke, which weakens least-privilege enforcement and increases the chance of unintended shell/env access.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The document's security section says there is no HTTP service, while another section explicitly advertises an optional background HTTP MCP server. Security-significant contradictions like this can cause unsafe deployment decisions, such as enabling the skill in environments that prohibit listeners or background services based on a mistaken belief that none exist.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file's user-facing descriptions, help text, prompts, and error messages are written in Chinese throughout, starting from the header comments and continuing in interactive output. For a general-purpose CLI, this imposes a specific language/locale on users without any opt-in, fallback, or explanation that the tool is region-specific.

Content

No source excerpt is available for this finding.

Scope Creep

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill metadata says environment-variable access requires explicit authorization, yet the file reads additional environment variables such as HEARTFLOW_MODEL_PROFILE and multiple memory-related flags by default. This violates the declared permission model and can expose deployment-specific configuration or secrets indirectly through behavior changes and trust boundary erosion.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The docstring at L2890-L2894 states disk writes are postponed to the next event-loop tick, but _saveAllMemories immediately calls _saveUserMemory, _saveSelfMemory, and _updateContextMemory, all of which use synchronous filesystem operations such as appendFileSync, readFileSync, and writeFileSync. _flushMemoryWrites does not perform deferred writes and merely sets a completion marker, so the comment materially misdescribes runtime behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

recordDialogue() persists full dialogue contents to disk in plaintext and this file does not enforce a user-facing confirmation or runtime consent check before doing so. Even on local systems, this can leak highly sensitive prompts, personal data, or secrets to other local users, backups, logs, or forensic tooling.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

toLocaleString('zh-CN', { hour12: false }) forces a specific locale in generated natural-language output. The file does not show an opt-in, locale negotiation, or justification that this skill is intended only for a Chinese-speaking or region-specific context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Natural-language guidance throughout the file, including the top-level description and method comments, is presented in Chinese with no indication that users may choose another language. This can violate a language/locale policy when a skill effectively forces a specific language without user opt-in or documented regional justification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This module persistently stores cross-session memories to disk (data/memory-bank.json) and exposes APIs for recall, transfer, summarization, and cross-session pattern detection, but the code itself contains no mechanism to obtain, record, or enforce explicit user consent before retaining data across sessions. In an AI skill handling potentially sensitive conversational content, undisclosed persistence increases privacy and data-retention risk, especially because long-term trends and user preferences can be inferred from accumulated records.

Content

No source excerpt is available for this finding.

Scope Creep

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

getInheritedContext('full') returns all persisted user and self memories with no access control, scope reduction, or consent check. In a memory component for an agent, broad retrieval of historical content increases the chance of unnecessary exposure of sensitive prior conversations, especially when the skill metadata says some capabilities require explicit authorization.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

recordUser writes user-provided content directly to persistent storage without any in-code consent, notice, or policy check. Even if another layer may disclose this behavior, this file itself enforces silent collection and retention of potentially sensitive conversation data, which creates privacy and compliance risk if invoked automatically.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

recordSelf persists model-derived internal outputs such as decisions, confidence, and insights to disk without any disclosure or policy gate. These records can contain sensitive inferences about the user or system behavior and may be surfaced later via inherited context, expanding privacy exposure beyond the immediate interaction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This manifest contains a user-facing description entirely in Chinese, presenting the skill identity and behavior in a single locale with no indication that users can choose another language. The policy requires flagging language or locale constraints when they are imposed without opt-in or clear justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
78% confidence
Finding

Natural-language strings, trigger heuristics, and complexity reasoning are predominantly defined around Chinese terms and Chinese-language interaction patterns, and the module description is presented in Chinese without any opt-in or locale selection. This can violate language/locale policy when a skill forces a specific language experience instead of letting users choose.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The pipeline does not only analyze and route; it also invokes a decision executor via exec.apply(...) using pipeline-derived decisions. If the executor is connected to side-effectful capabilities elsewhere in the skill, this turns analysis output into action without a strong authorization boundary in this file.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.