Back to skill

Security audit

Feedback Learning V2

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent feedback-learning tool, but it persistently stores raw feedback/errors and can automatically turn repeated feedback into active rules future agents may follow.

Install only if you want persistent local feedback telemetry and agent-behavior learning. Keep the learning directory private, avoid enabling the PostToolUse hook or cron until you have reviewed the data captured, redact secrets from feedback/error fields, and treat generated genes as suggestions requiring human approval before agents follow them.

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 (2)

T02 · Agent Memory Poisoning

Error
Location
scripts/analyze-patterns.py:77
Finding

Untrusted Feedback Can Be Promoted into Persistent Agent Rules

Content
View full analysis
" in hint: parts = hint.replace("->", "→").split("→", 1) condition = parts[0].strip() action = parts[1].strip() elif ev_type == "positive": condition = f"When doing: {signal}" action = f"Continue doing: {hint}" else: condition = f"When: {signal}" action = f"Instead: {hint}" return { "condition": condition[:200], "action": action[:200], "context": f"Observed {group['count']}x across agents: {sorted(group['agents'])}", } ``` `scripts/analyze-patterns.py:178-225` automatically promotes a repeated pattern into persistent `genes.json` state: ```python def promote_rules(neg_groups, genes_data): """Promote negative patterns that hit threshold and pass delta test.""" promoted = [] stagnated = [] for g in neg_groups: if g["count"] < PROMOTION_THRESHOLD: continue # Check if already promoted existing = next( (r for r in genes_data.get("rules", []) ...[truncated 4165 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/error-catcher.sh:14
Finding

Failed Commands and Error Output Are Persisted in Plaintext Without Redaction

Content
View full analysis
&2 exit 0 fi fi fi LINE="{\"ts\":\"$TS\",\"id\":\"$HASH\",\"agent\":$AGENT_J,\"type\":$TYPE_J,\"source\":$SOURCE_J,\"context\":$CONTEXT_J,\"signal\":$SIGNAL_J,\"hint\":$HINT_J,\"heat\":1}" echo "$LINE" >> "$EVENTS_FILE" ``` `scripts/weekly-report.py:117-120` copies event contents into persistent Markdown reports: ```python corrections = [e for e in events if e.get("type") == "correction"][:5] for e in corrections: report.append(f"- [{e.get('agent','?')}] {e.get('context','?')}: \"{e.get('signal','?')}\" → {e.get('hint','?')}") report.append("") ``` ### Technical Analysis Failed commands and stderr frequently contain secrets such as API tokens, passwords, private URLs, authorization headers, database connection strings, file paths, customer data, or portions of confidential documents. The hook truncates stderr to 200 characters but performs no secret redaction. More importantly, `TOOL_COMMAND` is retained without any length restriction or sanitization beyond JSON encoding. JSON encoding prevents malformed JSON but does not protect confidentiality. The captured values are appended to `events.jsonl` in plaintext. The script creates the targe ...[truncated 1566 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The code does match one subset of the description: zero-LLM bilingual feedback detection via shell/Python with no API keys. However, the declared purpose describes a broader feedback learning system with persistent logging, pattern tracking, rule promotion, behavioral delta testing, and weekly reporting. None of those capabilities appear in this code chunk. The actual code is limited to stateless detection/classification of feedback signals from text or emoji and JSON output. This is therefore a material description-behavior mismatch, with the implementation covering only the detector component of the claimed system.

Content

No source excerpt is available for this finding.

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · scripts/detect-feedback.py (reported line 16)May include surrounding context.

python
SON with type and details. No LLM needed — pure regex/pattern matching.
Supports Russian and English. Bilingual by design.

Usage:
  echo "переделай это" | python3 detect-feedback.py
  python3 detect-feedback.py "не так, сделай по-другому"
  python3 detect-feedback.py --pipe  # reads stdin, outputs nothing if "none"
"""
import re
import sys
import json

# === NLP TRIGGERS ===

NEGATIVE_RU = [
    r'\bфигня\b', r'\bпеределай\b', r'\bне\s+так\b', r'\bстоп\b',
    r'\bнеправильно\b', r'\bзаново\b', r'\bне\s+то\b', r'\bотмени\b',
    r'\bверни\b', r'\bоткати\b', r'\bне\s+надо\b', r'\bубери\b',
    r'\bхрень\b', r'\bфиг\w*\b', r'\bбред\b', r'\bчушь\b',
    r'\bне\s+работает\b', r'\bсломал\b', r'\bопять\b',
    r'\bужас\b', r'\bкошмар\b', r'\bплохо\b', r'\bневерно\b',
]

POSITIVE_RU = [
    r'\bкруто\b', r'\bтоп\b', r'\b�

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill instructs users to copy scripts, write files under a shared directory, chmod executables, and configure hooks/cron jobs, but it does not declare any explicit tool scope or permissions boundary. That makes the operational capabilities broader than the manifest suggests, increasing the risk that an agent or user enables file-write and environment-dependent behavior without clear review or sandboxing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill explicitly recommends logging command failure context and stderr, which often contain secrets, tokens, file paths, prompts, or user data. Because this is persisted to events.jsonl for later analysis, sensitive material can be silently retained and potentially exposed to other local processes, users, or future reports.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The PostToolUse hook enables background capture of tool output and errors after command execution without a prominent disclosure or consent mechanism. In agent environments, hook-based telemetry is especially sensitive because users may not realize that routine tool failures and outputs are being logged continuously.

Content

No source excerpt is available for this finding.

Tainted flow: 'GENES_FILE' from os.environ.get (line 21, 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/check-genes.py (reported line 33)May include surrounding context.

python
def save_genes(data):
    data["updated"] = datetime.now(timezone.utc).isoformat()
    with open(GENES_FILE, "w") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)

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.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script persists user-provided context, signal, and hint data directly to a local events log without any notice, consent, minimization, or redaction. In a feedback-learning skill, those fields can easily contain sensitive prompts, error output, personal data, or secrets, so silent retention increases privacy and data-exposure risk if the file is later read, backed up, or exfiltrated.

Content

No source excerpt is available for this finding.

Tainted flow: 'report_path' from os.environ.get (line 124, 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/weekly-report.py (reported line 125)May include surrounding context.

python
# Save report
    os.makedirs(REPORTS_DIR, exist_ok=True)
    report_path = os.path.join(REPORTS_DIR, f"WEEKLY_{week_str}.md")
    with open(report_path, "w") as f:
        f.write(report_text)

    print(f"✅ Report saved: {report_path}")

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The natural-language schedule examples hardcode the Europe/Moscow timezone, which imposes a locale-specific setting on all users. The document does not present this as an example to customize or explain why that locale is required, so it violates the language/locale policy criterion.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This code overwrites JSON files on disk via save_json(), which is a safety-relevant operation because it changes persistent local state. While runtime print statements exist elsewhere, there is no nearby disclosure in the write helper or top-level description that the script will update patterns.json and genes.json when run.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.