Back to skill

Security audit

Context Hawk

Security checks for vulnerabilities and agentic risk

Overview

Context-Hawk appears to be a real AI memory tool, but it needs Review because it persists and reuses conversation data while also recommending broad installers and shipping unsafe automation paths.

Install only after review. Prefer a virtual environment and pinned pip install instead of the one-line shell installer, avoid running the cron health-check script, and enable remote providers only if you are comfortable sending conversation and stored memory text to that provider. Keep memory stores isolated per user/project and periodically inspect or delete ~/.hawk data.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
Findings (5)

T03 · Remote Payload Retrieval and Execution

Error
Location
README.md:102
Finding

Mutable Remote Installer Is Downloaded and Executed Directly

Content
View full analysis
/dev/null; then bold "Installing Homebrew..." /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" \ > /dev/null 2>&1 || true eval "$(/opt/homebrew/bin/brew shellenv 2>/dev/null || true)" fi ``` Equivalent Context-Hawk commands occur at: - `README.de.md:108` - `README.es.md:72` - `README.fr.md:72` - `README.it.md:72` - `README.ja.md:106` - `README.ko.md:106` - `README.pt-BR.md:72` - `README.ru.md:72` - `README.zh-CN.md:106` - `README.zh-TW.md:106` `README.zh-CN.md:323` additionally recommends executing a mutable installer from the separate `relunctance/hawk-bridge` repository. ### Technical Analysis The documented command downloads shell code from the mutable `master` branch and immediately executes it through Bash. There is no immutable commit pin, versioned artifact, checksum, signature, or review step between retrieval and execution. Consequently, the effective installer payload can change after this project has been audited. Alt ...[truncated 1477 chars]
Remediation
View remediation

T02 · Agent Memory Poisoning

Error
Location
hawk/wrapper.py:139
Finding

Persistent Conversation Content Is Reintroduced as a System-Level Instruction

Content
View full analysis
str: """返回格式化后的 recall 结果,可直接注入上下文""" if not self._recalled_memories: return "" lines = ["🦅 ** hawk 记忆检索结果 **"] for c in self._recalled_memories: tag = f"[{c.category}]" if hasattr(c, 'category') else "" score = f"({getattr(c, 'score', 0):.0%})" if hasattr(c, 'score') else "" text = c.content if hasattr(c, 'content') else str(c) lines.append(f"{tag} {score} {text}") return "\n".join(lines) def chat(self, user_message: str, system_prompt: str = None) -> str: # 追加用户消息 self._conversation.append({"role": "user", "content": user_message}) # 构建消息(recall 结果注入) messages = [] if system_prompt: messages.append({"role": "system", "content": system_prompt}) recall_text = self.format_recall() if recall_text: messages.append({"role": "system", "content": recall_text}) messages.extend(self._conversation) response = self._call_llm(messages) ``` Conversation-derived text is persisted during capture: ```python conv_text = "\n".join( f"{'user' if m['role'] == 'user' else 'assistant'}: {m['content']}" for m in self._conversation[-6:] ) memories = extract_memories( conv_text, provider=self.cfg.provider, api_key=self.cfg.api_key, model=self.cfg.model, base_url=self.cfg.llm_base_url ) significant = [ m for m in memories if m.get("importance", 0) >= self.cfg.capture_threshold ] for m in significant: self.memory.store( text=m["text"], category=m.get("category", "other"), importance=m ...[truncated 2262 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/cron_health_check.sh:1
Finding

Health-Check Script Can Commit and Exfiltrate Arbitrary Repository Files

Content
View full analysis
> "$LOG" # 运行健康检查,捕获退出码 OUTPUT=$(python3 "$REPO/tests/health_check.py" 2>&1) EXIT=$? echo "$OUTPUT" >> "$LOG" if [ $EXIT -ne 0 ]; then echo "[$DATE] ❌ Tests failed, committing fixes..." >> "$LOG" # 有测试失败,尝试自动修复 git add -A git commit -m "fix: auto-fix from health check cron [$DATE]" git push >> "$LOG" 2>&1 echo "[$DATE] ✅ Fixes committed and pushed" >> "$LOG" else echo "[$DATE] ✅ All tests passed, no changes needed" >> "$LOG" fi ``` ### Technical Analysis When any health check fails, the script runs `git add -A`, which stages all modifications, deletions, and untracked files in the entire repository. It then commits and pushes those files to the configured remote. The script contains no actual repair step between test failure and the statement that it is “committing fixes.” Therefore, the pushed content consists of whatever was already present in the working tree, including unrelated work, generated files, logs, accidentally copied credentials, or attacker-created files. There is no path allowlist, diff review, secret scanning, remote validation, branch restriction, or manual approval. Although the repository contains a script named as a cron health check, the reviewed installation scripts do not themselves install a cron entry; system persistence is therefore not confirmed. ### Attack Path 1. A sensitive or attacker-controlled file is created anywhere under the repository. 2. The attacker or an ordinary software defect causes `tests/health_check.py` to return a nonzero exit status. ...[truncated 925 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
install.sh:119
Finding

Installer Performs Unnecessary Privileged System-Wide Package Changes

Content
View full analysis
/dev/null 2>&1 ;; fedora) dnf install -y -q \ python3 python3-pip \ git curl \ gcc gcc-c++ make \ openssl-devel zlib-devel \ > /dev/null 2>&1 ;; arch) pacman -Sy --noconfirm \ python python-pip \ git curl \ base-devel \ > /dev/null 2>&1 ;; alpine) apk add --no-cache \ python3 py3-pip \ git curl \ build-base openssl-dev zlib-dev \ > /dev/null 2>&1 ;; suse) zypper install -y -q \ python3 python3-pip \ git curl \ gcc gcc-c++ make \ libopenssl-devel zlib-devel \ > /dev/null 2>&1 ;; esac } ``` The installer also upgrades pip in the selected interpreter: ```bash "$PYTHON_CMD" -m pip install --upgrade pip -q 2>/dev/null || true log "pip ready" ``` ### Technical Analysis The installer invokes operating-system package managers and installs compilers, development headers, Git, curl, and other h ...[truncated 1646 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
install.sh:258
Finding

Unpinned Dependencies and Mutable Git Fallback Create Supply-Chain Exposure

Content
View full analysis
/dev/null; then log "Installed context-hawk from PyPI" else warn "context-hawk not found on PyPI, falling back to git+https install" if "$PYTHON_CMD" -m pip install "git+${REPO_URL}.git" -q 2>/dev/null; then log "Installed context-hawk from git" else warn "Could not install context-hawk from pip/git, installing dependencies manually" FALLBACK_PACKAGES=( "lancedb>=0.10" "rank-bm25>=0.2" "openai>=1.0" "tiktoken>=0.7" "sentence-transformers>=2.0" "httpx>=0.25" ) for pkg in "${FALLBACK_PACKAGES[@]}"; do "$PYTHON_CMD" -m pip install "$pkg" -q 2>/dev/null done fi fi } ``` The secondary installer is also unpinned: ```bash # 2. 安装核心依赖 $PYTHON -m pip install lancedb openai -q ``` Project metadata uses open-ended minimum versions: ```toml dependencies = [ "lancedb>=0.10", "rank-bm25>=0.2", "tiktoken>=0.7", ] [project.optional-dependencies] api = ["openai>=1.0"] all = [ "openai>=1.0", "sentence-transformers>=2.0", "httpx>=0.25", ] ``` ### Technical Analysis The installation process resolves packages dynamically without exact versions or cryptographic hashes. The Git fallback installs directly from the repository's default branch because no tag or immutable commit is specified. Python package installation can execute build backe ...[truncated 1530 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (150)

Tainted flow: 'req' from os.environ.get (line 358, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The Groq fallback path sends conversation text plus a bearer token to an external API endpoint, using credentials obtained from environment variables or CLI input. This creates a real exfiltration path for sensitive conversation data to a remote service and could disclose API credentials if configuration is mishandled or logs capture outbound headers.

Content

Scanner excerpt · hawk/extractor.py (reported line 271)May include surrounding context.

python
"Content-Type": "application/json",
            }
        )
        with urllib.request.urlopen(req, timeout=30) as resp:
            result = json.loads(resp.read())
            content = result["choices"][0]["message"]["content"]
            return parse_and_validate(content)

Tainted flow: 'req' from os.environ.get (line 263, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · hawk/extractor.py (reported line 305)May include surrounding context.

python
data=data,
        headers={"Content-Type": "application/json"}
    )
    with urllib.request.urlopen(req, timeout=60) as resp:
        result = json.loads(resp.read())
        content = result["message"]["content"]
        return parse_and_validate(content)

Tainted flow: 'req' from os.environ.get (line 263, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
92% confidence
Finding

The code transmits full conversation content and an authorization token to OpenRouter over the network, with credentials sourced from arguments or environment variables. If sensitive conversations are processed without explicit consent or data-classification checks, this can leak private user data and secrets to a third-party provider.

Content

Scanner excerpt · hawk/extractor.py (reported line 333)May include surrounding context.

python
"X-Title": "hawk-bridge",
        }
    )
    with urllib.request.urlopen(req, timeout=30) as resp:
        result = json.loads(resp.read())
        content = result["choices"][0]["message"]["content"]
        return parse_and_validate(content)

Tainted flow: 'req' from os.environ.get (line 358, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
91% confidence
Finding

The OpenClaw fallback path builds a remote chat URL from a configurable base URL and sends both conversation content and an authorization token to that destination. Because the base URL can come from environment configuration, a misconfigured or malicious value could route sensitive user data and credentials to an unintended third party.

Content

Scanner excerpt · hawk/extractor.py (reported line 366)May include surrounding context.

python
"Content-Type": "application/json",
            }
        )
        with urllib.request.urlopen(req, timeout=30) as resp:
            result = json.loads(resp.read())
            content = result["choices"][0]["message"]["content"]
            return parse_and_validate(content)

Tainted flow: 'req' from os.environ.get (line 249, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · hawk/wrapper.py (reported line 257)May include surrounding context.

python
"Content-Type": "application/json",
                }
            )
            with urllib.request.urlopen(req, timeout=60) as resp:
                result = json.loads(resp.read())
                return result["choices"][0]["message"]["content"]

Tainted flow: 'req' from os.environ.get (line 249, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · hawk/wrapper.py (reported line 301)May include surrounding context.

python
"Content-Type": "application/json",
                }
            )
            with urllib.request.urlopen(req, timeout=60) as resp:
                result = json.loads(resp.read())
                return result["choices"][0]["message"]["content"]

Tainted flow: 'req' from os.environ.get (line 249, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · hawk/wrapper.py (reported line 280)May include surrounding context.

python
data=json.dumps({"model": self.cfg.model, "messages": messages, "stream": False}).encode(),
            headers={"Content-Type": "application/json"}
        )
        with urllib.request.urlopen(req, timeout=120) as resp:
            result = json.loads(resp.read())
            return result["message"]["content"]

Ssd 3

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

This section describes storing 'complete original content' and enabling shared cross-agent memory, which materially increases the chance that sensitive user data, secrets, documents, or prior conversation content will be broadly retained and exposed to other sessions or agents. The danger is amplified by the combination of persistence, sharing, and apparently broad collection semantics without clear minimization, access control, or redaction guarantees.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README states that all agents can read and write the same shared memory, which broadens access to user-derived data beyond the original interaction boundary. In multi-agent environments this can cause confidentiality violations, inappropriate context propagation, and accidental leakage of sensitive material to agents with different roles, permissions, or trust levels.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The README describes shared memory where all agents read and write the same memory store, which materially increases the risk of cross-agent data leakage and unauthorized context propagation. This is especially dangerous because information disclosed to one agent may later be exposed to another agent operating under different trust assumptions or permissions.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The structured memory example includes a field for storing 'complete raw content', which encourages verbatim persistence of conversations or documents. That design increases the likelihood that secrets, credentials, personal data, or proprietary text are retained long-term and later disclosed through recall, backup, or compromise of the memory store.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The implementation of dry_run is unsafe because it still invokes the real strategy functions, and those functions mutate and persist state via self.mm._save(). That means a caller expecting a harmless preview can accidentally summarize, extract, delete, promote, or archive memories, causing data loss or unintended external transmission.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
70% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · hawk/config.py (reported line 169)May include surrounding context.

python
_float_keys = {'decay_rate', 'recall_min_score', 'capture_importance_threshold',
                       'importance_threshold_low', 'importance_threshold_high', 'compress_ratio_threshold',
                       'summary_max_chars'}
        for env_key in os.environ:
            if env_key.startswith('HAWK_'):
                config_key = env_key[len('HAWK_'):].lower()
                if config_key and config_key in self._config:

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The module claims incremental import and deduplication, but embed_and_store unconditionally drops and recreates the LanceDB table before writing new rows. This can silently destroy previously stored memory data, especially when scan() skips files already tagged as imported, causing data loss and inconsistency between source files and the database.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The import_all interface advertises a safe incremental operation, but it invokes embed_and_store, which replaces the entire table. In this skill context, that mismatch is dangerous because users may trust it for background memory ingestion and unintentionally wipe stored knowledge while files marked as already imported are skipped.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

The script advertises execution via curl | bash, which encourages users to run unreviewed network-delivered code directly in a shell. This pattern is dangerous because any compromise of the distribution channel immediately becomes arbitrary code execution on the user's machine.

Content

Scanner excerpt · install.sh (reported line 5)May include surrounding context.

sh
# context-hawk one-command install script
# Supports: Ubuntu/Debian, Fedora/RHEL/CentOS/Rocky/AlmaLinux, Arch, Alpine, openSUSE, macOS
# Usage:
#   curl -fsSL https://.../install.sh | bash
#   ./install.sh --help
#
set -euo pipefail

Chaining Abuse

High
Category
Tool Misuse
Confidence
91% confidence
Finding

The documented chaining pattern pipes downloaded content directly into bash, removing the user's chance to inspect the script before execution. In the skill context, this is more dangerous because the installer already performs system-level package installs and additional remote fetches, compounding the blast radius of any compromise.

Content

Scanner excerpt · install.sh (reported line 5)May include surrounding context.

sh
# context-hawk one-command install script
# Supports: Ubuntu/Debian, Fedora/RHEL/CentOS/Rocky/AlmaLinux, Arch, Alpine, openSUSE, macOS
# Usage:
#   curl -fsSL https://.../install.sh | bash
#   ./install.sh --help
#
set -euo pipefail

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · install.sh (reported line 47)May include surrounding context.

sh
echo ""
    echo "Options:"
    echo "  --help         Show this help message"
    echo "  --force        Overwrite existing config and installation"
    echo "  --skip-deps    Skip system dependency installation"
    echo ""
    echo "Supported OS:"

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

The --noconfirm parameter disables safety prompts for pacman, reducing user control over privileged package installation. In an installer skill, this is a meaningful abuse-prone parameter because it enables silent system changes.

Content

Scanner excerpt · install.sh (reported line 148)May include surrounding context.

sh
;;

        arch)
            pacman -Sy --noconfirm \
                python python-pip \
                git curl \
                base-devel \

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Using --noconfirm in the fallback path is especially risky because it combines uncertain environment detection with silent privileged actions. That can result in inappropriate package operations without review.

Content

Scanner excerpt · install.sh (reported line 192)May include surrounding context.

sh
elif command -v dnf &> /dev/null; then
                dnf install -y -q python3 python3-pip git curl gcc make > /dev/null 2>&1 || true
            elif command -v pacman &> /dev/null; then
                pacman -Sy --noconfirm python python-pip git curl base-devel > /dev/null 2>&1 || true
            fi
            ;;
    esac

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
89% confidence
Finding

The pip-repair path uses pacman --noconfirm, again disabling user review for a system change. Even if intended for convenience, it lowers safety boundaries and can surprise users in automated or managed environments.

Content

Scanner excerpt · install.sh (reported line 240)May include surrounding context.

sh
dnf install -y -q python3-pip > /dev/null 2>&1 || true
                ;;
            arch)
                pacman -Sy --noconfirm python-pip > /dev/null 2>&1 || true
                ;;
            alpine)
                apk add --no-cache py3-pip > /dev/null 2>&1 || true

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · references/task-state.md (reported line 32)May include surrounding context.

md
"steps": [
    {
      "id": 1,
      "description": "Write SKILL.md",
      "status": "completed",
      "done_at": "2026-03-29T00:15:00+08:00"
    },

Ssd 3

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill advertises silently remembering and reapplying user preferences across sessions, which means user-provided behavioral and contextual data is retained and reused without any visible consent or scoping controls in this document. That creates a privacy and data-leakage risk, especially when sensitive preferences, instructions, or contextual details are later injected into unrelated sessions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The README explicitly recommends executing a remote script directly via bash <(curl ...), which bypasses normal review of downloaded code and creates a direct supply-chain execution path. If the remote repository, transport, or referenced script is compromised, users may execute attacker-controlled code on their systems immediately.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documented 'E: Voll' strategy says no filter is applied, meaning all stored memory may be injected into model context. This can cause unrelated, stale, or sensitive retained data to be surfaced to the model and potentially reflected in outputs, turning persistence into an unintended disclosure channel.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.