Back to skill

Security audit

Abby Autonomy

Security checks for vulnerabilities and agentic risk

Overview

This skill is not malicious, but it needs review because it is designed to run recurring autonomous work and its queue state handling can repeat or lose tasks.

Review before installing. Use this only if you intentionally want an agent to poll a local task queue and work without asking every time. Keep the queue limited to trusted, low-impact tasks, do not wire it to financial/account-changing or costly external actions until the queue-claim and parsing bugs are fixed, and make sure any cron or scheduler can be paused quickly.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/queue.py:121
Finding
Non-Persistent Task Transition Allows Repeated Autonomous Execution and Queue Corruption<![CDATA[ ## Vulnerability Details **File Location**: `scripts/queue.py:72-74, 121-140, 195-199`; `scripts/heartbeat.py:66-76, 89-91, 137-147` **Vulnerability Type**: Non-atomic state transition and inconsistent queue parsing **Risk Level**: Medium ### Vulnerable Code ```python # scripts/queue.py:72-74 elif line.startswith('- [ ]') and current_section: task = line.replace('- [ ]', '').strip() result[current_section].append(task) ``` ```python # scripts/queue.py:121-140 def take_task(self, queue: Dict) -> Optional[str]: """ 取最高优先级的任务 Args: queue: 当前队列 Returns: str: 任务内容 或 None """ if not queue.get('ready'): return None # 取第一个任务 task = queue['ready'].pop(0) # 移到进行中 queue['in_progress'].append(task) return task ``` ```python # scripts/queue.py:195-199 def take_task() -> Optional[str]: """取任务""" q = TaskQueue() queue = q.read_queue() return q.take_task(queue) ``` ```python # scripts/heartbeat.py:66-76 # 3. 从队列取任务 queue = self.queue.read_queue() task = self.queue.take_task(queue) if task: print(f"[{datetime.now().strftime('%H:%M:%S')}] 开始新任务: {task}") # 4. 标记状态 self.state.start_task(task, estimated_minutes=30) return task ``` ```python # scripts/heartbeat.py:89-91 # 更新队列 if success: complete_task(task) ``` ```python # scripts/heartbeat.py:137-147 if __name__ == '__main__': # 测试心跳 print("="*50) print("Abby Autonomy Heartbeat 测试") print("="*50) result = run_heartbeat() if result: print(f"\n开始执行任务: {result}") start_working(result) ``` ### Technical Analysis `TaskQueue.take_task()` removes the selected task from the in-memory `ready` list and appends it to the in-memory `in_progress` list, but it never calls `write_queue()` to persist this transition. The module-level `take_task()` and heartbeat workflow likewise return the selected task without saving the modified queue. When the task completes, `comp ...[truncated 2844 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Persist task claiming before returning the selected task: ```python def take_task(self, queue: Dict) -> Optional[str]: if not queue.get("ready"): return None task = queue["ready"].pop(0) queue.setdefault("in_progress", []).append(task) if not self.write_queue(queue): # Do not execute a task whose claim was not persisted. return None return task ``` 2. Make the claim operation atomic: - Acquire an exclusive lock before reading and modifying the queue. - Read, validate, modify, and write while holding the same lock. - Write to a temporary file in the same directory, flush and `fsync()` it, and replace `QUEUE.md` with `os.replace()`. - Release the lock only after the replacement succeeds. 3. Correctly parse checked entries by section. Ready and Blocked may use `- [ ]`, while In Progress and Done use `- [x]`. Do not discard entries solely because they are checked. 4. Assign each task a stable unique identifier instead of using the full task description as its identity. Require completion and pause operations to reference that identifier. 5. Validate state transitions: - Permit completion only when the task exists in In Progress. - Prevent duplicate IDs across sections. - If persistence fails, fail closed and do not begin execution. - On task failure, atomically move the task to Ready or Blocked rather than only clearing runtime state. 6. Protect against concurrent heartbeat execution with a process-level singleton lock or transactional queue backend. 7. Add automated tests covering: - Persistence immediately after claiming a task. - Two simultaneous heartbeat processes. - Restart between claim and completion. - Parsing and preservation of checked In Progress and Done entries. - Write failures and malformed queue files. - Repeated heartbeat runs confirming that a completed task is not selected again. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (10)

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill describes recurring autonomous execution that reads tasks and writes queue/state data, but it does not clearly warn users that files will be modified automatically on a heartbeat. Lack of disclosure is risky because users may not realize that the agent will continuously mutate task and memory artifacts, which can lead to confusion, accidental overwrites, audit gaps, or unintended workflow changes.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The skill explicitly promotes acting whenever the agent is idle and emphasizes that it should 'always have work to do,' but it does not define strong boundaries on what conditions permit autonomous execution or when it must defer to a user. In an agent context, broad idle-time activation can cause unintended actions, repeated task execution, or execution of stale/unsafe queued work without an explicit authorization checkpoint.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This code file contains natural-language strings that define the skill’s purpose and behavior entirely in Chinese, such as the module docstring and later console messages. Because the file provides no opt-in, fallback, or justification for a Chinese-only locale, it violates the language/locale policy requirement.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This code file contains natural-language instructions and descriptions only in Chinese, including the module header and operational docstrings. Under the policy rule, forcing a specific language without user opt-in or documented locale justification is a language/locale policy concern.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The top-level take_task() function reads the queue and mutates the in-memory structure by moving a task from ready to in_progress, but it never calls write_queue() to persist that state change. In a task-execution skill, this can cause duplicate task claims, lost state transitions, and race-prone behavior where multiple agents believe they own the same task.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The module title and all user-facing natural-language descriptions are written only in Chinese, indicating a language-specific skill without any visible opt-in or alternative language support. Under the policy, forcing a specific language without user choice is a natural-language locale violation unless clearly justified as region-specific.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
This code file contains natural-language text in Chinese ("自主任务执行系统") alongside English, but does not indicate that the skill is locale-specific or that users may choose their preferred language. Under the language/locale policy rule, forcing or assuming a language without opt-in can be a policy concern.

Intent-Code Divergence

Low
Confidence
93% confidence
Finding
The top-level documentation describes a recurring behavior ('每3分钟检查并主动工作'), which implies periodic execution. In the actual code, `run_heartbeat()` performs one pass only, and the `__main__` block just invokes it once without any timer, loop, or scheduler.

Intent-Code Divergence

Low
Confidence
89% confidence
Finding
The docstring and function name suggest this function executes the provided task. However, the body explicitly marks real execution as TODO and only prints a message, sleeps, and emits synthetic progress, which contradicts the claimed operational behavior.

Natural-Language Policy Violations

Low
Confidence
83% confidence
Finding
This markdown file contains user-facing natural language in both Chinese and English, including Chinese-only task descriptions such as "等待爸爸确认策略参数" and labels like "最后更新", without any indication that the user opted into that locale mix. The stated policy requires flagging language or locale constraints when the skill effectively forces a specific language without user opt-in or justification.

Static analysis

No suspicious patterns detected.