Back to skill

Security audit

session-archivist

Security checks for vulnerabilities and agentic risk

Overview

This skill has a coherent session-cleanup purpose, but it can automatically rewrite conversation history, persist summaries, send them to a memory service, and install a recurring task.

Install only if you want this skill to modify Hermes session files automatically. Run dry-run first, disable Hindsight unless you explicitly want summaries stored in a memory service, review the cron job before enabling it, and keep independent backups because trimming is lossy and built-in full backups expire after seven days.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (4)

T06 · System Persistence

Error
Location
scripts/setup_cron.sh:39
Finding

Persistent Daily Agent Task Is Installed by the Setup Script

Content
View full analysis
/dev/null || { echo " ⚠ Could not create hermes cron job" echo " You can manually add it later:" echo " hermes cron create '0 3 * * *' --name session-archivist-daily --prompt 'python3 $ARCHIVER'" } ``` ### Technical Analysis The setup script registers a daily Hermes cron task that persists after the setup process and across Agent sessions. The scheduled task instructs an Agent to execute `session_archiver.py`, which scans, reads, archives, optionally transmits, and rewrites qualifying session files. The installation is documented and therefore is not hidden. Nevertheless, it creates a persistent execution mechanism with broad access to the invoking user's Hermes session data. The setup process does not request a separate confirmation immediately before persistence is installed, display a removal command, or constrain the scheduled operation to a narrowly scoped non-Agent executable action. ### Attack Path 1. A user follows the documented installation instructions and runs `scripts/setup_cron.sh`. 2. The script creates the `session-archivist-daily` recurring Hermes task. 3. At 03:00 each day, Hermes receives a prompt instructing it to execute the archiver. 4. The archiver scans all qualifying sessions under the configured Hermes home directory. 5. Sessions may be archived, sent to Hindsight, and destructively trimmed without per-run user approval. ### Impact Assessment The task runs with the permissions of the Hermes user. It does not directly escalate operating-system privileges, but it persistsently exercises that user's access to Hermes session files and configured mem ...[truncated 277 chars]
Remediation
View remediation

T02 · Agent Memory Poisoning

Error
Location
scripts/session_archiver.py:705
Finding

Untrusted Conversation Content Is Persisted as a System-Level Message

Content
View full analysis
str: """Extract user intent from the first few user messages.""" user_msgs = [m for m in messages[:20] if m.get("role") == "user" and m.get("content")] if not user_msgs: return "_(no user messages found)_" first = user_msgs[0].get("content", "")[:500] return f'> {first}' ``` Additional conversation lines are also copied into the summary: ```python if any(kw in line for kw in ["决定", "选择", "方案", "确定", "结论"]): if len(line) > 10: decisions.append(f"- {line[:200]}") ``` The generated summary is then elevated into a system-role message: ```python def _trim_session(self, data: dict, messages: list, scores: list, summary: str) -> dict: """Trim the session, retaining recent messages and summary context.""" keep_count = min(self.keep_recent, len(messages)) recent_messages = messages[-keep_count:] summary_msg = { "role": "system", "content": f"[Session Archivist] 此会话已被归档。以下是历史摘要:\n\n{summary[:2000]}", "timestamp": datetime.now(timezone.utc).timestamp(), } trimmed_messages = [summary_msg] + recent_messages data["messages"] = trimmed_messages data["_session_archivist"] = { "archived_at": datetime.now(timezone.utc).isoformat(), "original_count": len(messages), "trimmed_count": len(trimmed_messages), } return data ``` ### Technical Analysis Conversation content is untrusted data. The summary generator extracts text directly from user messages and other session messages based on simple keyword rules. It does not distinguish factual archival material from instruction-like te ...[truncated 2013 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/session_archiver.py:416
Finding

Sensitive Session Summaries Can Be Transmitted to a Configurable Plaintext Endpoint

Content
View full analysis
str: """Store a memory and return its memory ID.""" import urllib.request payload = json.dumps({ "items": [{ "content": content, "metadata": {k: str(v) for k, v in metadata.items()}, "tags": tags, "document_id": f"session_{metadata.get('session_id', 'unknown')}", "timestamp": metadata.get("archived_at", datetime.now(timezone.utc).isoformat()), }], "async": False, }).encode() req = urllib.request.Request( f"{self.url}/v1/default/banks/{bank_id}/memories", data=payload, headers={"Content-Type": "application/json"}, method="POST" ) with urllib.request.urlopen(req, timeout=30) as resp: data = json.loads(resp.read()) if data.get("success"): return f"bank:{bank_id}:stored" return "" ``` The transmitted content is derived from archived sessions: ```python memory_id = self.hindsight.store_memory( bank_id=bank_id, content=summary, metadata={ "session_id": session_id, "archived ...[truncated 2022 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/session_archiver.py:649
Finding

Destructive Session Trimming Can Permanently Delete Original Conversation Data

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (28)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The documented purpose understates materially sensitive behaviors: reading gateway logs/process state, injecting summary content into sessions, creating/deleting backups, and exporting summaries to an external memory bank. This mismatch is dangerous because users may invoke the skill expecting local maintenance only, while it can alter session history and move potentially sensitive content into other storage systems or over HTTP.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Archived summaries are transmitted to the Hindsight memory service, extending user conversation data beyond the original session boundary into another persistence layer. This is especially dangerous in the skill context because the summaries aggregate important content and references, making concentrated sensitive data available to another service over HTTP.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README advertises optional Hindsight integration that automatically stores archived content into a memory database, but it does not clearly explain what data leaves the primary session file, where it is stored, or the privacy implications. Because session archives can contain sensitive prompts, decisions, errors, and quoted content, silent or poorly disclosed secondary storage creates meaningful confidentiality and compliance risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README instructs users to run an archiver and set up a cron job that will automatically trim session files, but it does not prominently warn that original conversation histories will be modified and reduced. In a tool that operates on persistent session state, lack of explicit disclosure increases the risk of unintended data loss and can mislead users into enabling destructive automation without understanding the consequences.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill advertises shell execution, file writes, environment access, and possible network use, but declares no explicit tool scope or permissions boundary. In an agent ecosystem, this increases the chance of over-privileged execution, accidental destructive actions on session files, or silent exfiltration paths via optional integrations such as Hindsight.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill processes and archives conversation content that may contain credentials, personal data, source code, or internal decisions, yet it provides no clear warning that this data may be stored in markdown archives, backups, or transmitted to Hindsight. This can lead to unintentional persistence and broader exposure of sensitive data beyond the original session context.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation expands a local session-archiving skill into an external vector-memory integration that sends archived session content to another service. That materially changes the trust boundary and data-handling model without clear disclosure in the skill description, creating risk of unintended retention or exposure of sensitive session data.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

Automatic health checks and automatic storage to a network service exceed the stated purpose of simple session-file maintenance and introduce external communication and persistence. Even though the endpoint is localhost, this can still expose sensitive archived content to another process or service without meaningful user awareness.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The guide describes automatic HTTP probing and automatic archival to Hindsight without warning users that session content may be transmitted to and stored in a separate service. This lack of transparency is dangerous because archived sessions often contain sensitive prompts, code, secrets, or business context, and users may reasonably expect purely local file maintenance.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The documentation states that stored memories are processed by an LLM and transformed during storage, but it does not warn users that archived content will undergo external model processing. This can expose confidential or regulated data to additional processing layers and retention pathways beyond simple storage.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The template explicitly instructs archived summaries to include file paths, config keys/values, and localhost API endpoints. Those details can expose sensitive environment structure, internal services, and secrets or quasi-secrets in configuration, which is especially risky because archives are meant to persist and may be shared more broadly than the original session.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The extraction rules direct the skill to mine filesystem paths and local API references from session content without any warning, minimization, or sanitization requirement. In a session-archiving skill, this increases the chance that sensitive host details are systematically collected into durable summaries, expanding the blast radius of any later disclosure.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The summary generator persists user-derived content such as the first user message and other extracted material without any sensitivity filtering. Because sessions can contain secrets, personal data, internal instructions, or proprietary references, indiscriminate summarization and retention increase the chance of long-lived exposure locally and in downstream systems.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The tool deliberately extracts filesystem paths and localhost URLs from conversation content and writes them into archive summaries. Even if these are not internet endpoints, they can reveal internal topology, project structure, sensitive filenames, and service locations that were previously only present transiently in chat history.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill presents itself as session lifecycle management, but the implementation can export archived session summaries to a separate Hindsight service over HTTP. Because those summaries include user content and extracted references, this creates a confidentiality boundary violation and undisclosed data egress beyond what the skill description suggests.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The code inspects host processes and parses gateway logs to infer active sessions, giving the skill visibility into broader host activity than simple session file management requires. In a plugin/skill context, this increases privacy and observability risk because it can expose unrelated runtime information and session identifiers from the local environment.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/session_archiver.py (reported line 468)May include surrounding context.

python
try:
        # 检查 hermes gateway 进程
        import subprocess
        result = subprocess.run(
            ["pgrep", "-a", "-f", "hermes_cli.main gateway"],
            capture_output=True, text=True, timeout=5
        )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/session_archiver.py (reported line 495)May include surrounding context.

python
try:
        import subprocess
        # 检查是否有 hermes agent 进程正在运行
        result = subprocess.run(
            ["pgrep", "-f", "run_agent"],
            capture_output=True, timeout=5
        )

Tainted flow: 'archive_path' from os.environ.get (line 643, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/session_archiver.py (reported line 649)May include surrounding context.

python
print(f"  [DRY-RUN] Would trim to ~{self.keep_recent} messages")
        else:
            # 写入本地 markdown
            with open(archive_path, "w") as f:
                f.write(summary)
            print(f"  ✅ Archived to: {archive_path}")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Session summaries are sent to Hindsight automatically when enabled, with no explicit user prompt, warning, or confirmation in the archiving flow. Since archived content may contain sensitive conversation text, decisions, file paths, and localhost URLs, silent propagation materially raises data leakage risk.

Content

No source excerpt is available for this finding.

Tainted flow: 'backup_path' from os.environ.get (line 679, credential/environment) → shutil.copy2 (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/session_archiver.py (reported line 680)May include surrounding context.

python
# 6. 备份 + 裁剪
            backup_path = BACKUP_DIR / f"{session_id}_{datetime.now().strftime('%Y%m%d')}.json"
            shutil.copy2(session_path, backup_path)
            print(f"  📦 Backup: {backup_path}")

            trimmed = self._trim_session(data, messages, scores, summary)

Ssd 3

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The trimming logic injects a synthesized system message containing archival summary content back into the remaining session. Reintroducing historical user data as a system-level message can amplify sensitive information, alter model behavior with stale or over-privileged context, and cause repeated retention of data that users may expect to have been trimmed away.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The prominent subtitle and the rest of the user-facing README are in Chinese, which can amount to an implicit language constraint when no alternative language or opt-in is provided. The file does not state that the skill is region-specific or offer users a language choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill title and nearly all operational documentation are written in Chinese, with no indication that users may choose another language or that the skill is intended only for a Chinese-speaking or region-specific audience. Under the language/locale policy, forcing a specific language without user opt-in can be a natural-language policy issue.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The manifest focuses on archiving old sessions and compression-related lifecycle management. The documented workflow of searching Hindsight by keyword and resuming sessions from returned identifiers introduces a retrieval/knowledge-memory capability that goes beyond straightforward session size control.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.