Back to skill

Security audit

Palest Ink - Activity Tracker

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed activity tracker, but it installs persistent, broad monitoring of highly sensitive local activity by default and has under-scoped controls.

Install only if you are comfortable with continuous local logging of browsing, commands, app/window titles, editor activity, Git metadata, and file paths. Review and disable collectors you do not need before running the installer, avoid granting broad Terminal permissions unless necessary, and be aware that the Git hook and URL-content features carry security risks beyond simple local note-taking.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
Findings (5)

T06 · System Persistence

Error
Location
collectors/install.sh:123
Finding

Persistent LaunchAgent Executes the Full Collection Pipeline Every 15 Seconds

Content
View full analysis
/dev/null | grep -q "palest-ink"; then warn "Removing old cron job..." crontab -l 2>/dev/null | grep -v "palest-ink" | crontab - fi if launchctl list | grep -q "$PLIST_LABEL" 2>/dev/null; then launchctl unload "$PLIST_PATH" 2>/dev/null || true fi cat > "$PLIST_PATH" << PLISTEOF Label ${PLIST_LABEL} ProgramArguments /bin/bash ${PALEST_INK_DIR}/bin/cron_collect.sh StartInterval 15 StandardOutPath ${PALEST_INK_DIR}/cron.log StandardErrorPath ${PALEST_INK_DIR}/cron.log RunAtLoad PLISTEOF launchctl load "$PLIST_PATH" ``` The persisted entry invokes the complete pipeline: ```bash timeout 5 python3 "$BIN_DIR/collect_app.py" 2>&1 || true python3 "$BIN_DIR/collect_chrome.py" 2>&1 || true python3 "$BIN_DIR/collect_safari.py" 2>&1 || true python3 "$BIN_DIR/collect_content.py" 2>&1 || true python3 "$BIN_DIR/collect_shell.py" 2>&1 || true python3 "$BIN_DIR/collect_vscode.py" 2>&1 || true python3 "$BIN_DIR/collect_git.py" 2>&1 || true timeout 15 python3 "$BIN_DIR/collect_fsevent.py" 2>&1 || true ``` ### Technical Analysis The installer registers a per-user LaunchAgent w ...[truncated 1761 chars]
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Error
Location
collectors/git_hook.sh:27
Finding

Global Git Hook Hijacking Enables Python Source Injection from Repository-Controlled Values

Content
View full analysis
/dev/null || echo "") if [ -n "$EXISTING_HOOKS_PATH" ] && [ "$EXISTING_HOOKS_PATH" != "$PALEST_INK_DIR/hooks" ]; then warn "Existing global hooksPath found: $EXISTING_HOOKS_PATH" warn "Backing up to config.json" python3 -c " import json with open('$PALEST_INK_DIR/config.json', 'r') as f: cfg = json.load(f) cfg['previous_hooks_path'] = '$EXISTING_HOOKS_PATH' with open('$PALEST_INK_DIR/config.json', 'w') as f: json.dump(cfg, f, indent=2) " fi for hook in post-commit post-merge post-checkout pre-push; do cp "$SCRIPT_DIR/git_hook.sh" "$PALEST_INK_DIR/hooks/$hook" chmod +x "$PALEST_INK_DIR/hooks/$hook" done git config --global core.hooksPath "$PALEST_INK_DIR/hooks" ``` The hook interpolates repository-controlled strings directly into Python source: ```bash REPO=$(git rev-parse --show-toplevel 2>/dev/null || echo "unknown") HASH=$(git rev-parse HEAD 2>/dev/null || echo "unknown") BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown") MESSAGE=$(git log -1 --pretty=%s 2>/dev/null || echo "") python3 -c " import json record = { 'ts': '$TIMESTAMP', 'type': 'git_commit', 'source': 'git_hook', 'data': { 'repo': '$REPO', 'branch': '$BRANCH', 'hash': '$HASH', 'message': $(json_escape "$MESSAGE"), 'files_changed': $FILES_JSON, 'insertions': int('${INSERTIONS:-0}'), 'deletions': int('${DELETIONS:-0}') } } with open('$DATAFILE', 'a') as f: f.write(json.dumps(record, ensure_ascii=False) + '\n') " 2>/dev/null ``` The pre-push hook repeats the same unsafe ...[truncated 2571 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
collectors/collect_content.py:97
Finding

Automatic URL Refetching Allows SSRF and Disclosure of Secret-Bearing URLs

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
collectors/collect_shell.py:151
Finding

Sensitive Activity Data Is Stored Verbatim Without Enforced Access Controls or Secret Redaction

Content
View full analysis
1000: continue record = { "ts": dt.isoformat(), "type": "shell_command", "source": "shell_collector", "data": { "command": cmd, "duration_seconds": duration, } } datafile = get_datafile(dt) if datafile not in records_by_file: records_by_file[datafile] = [] records_by_file[datafile].append(record) for datafile, records in records_by_file.items(): with open(datafile, "a") as f: for record in records: f.write(json.dumps(record, ensure_ascii=False) + "\n") ``` The installer creates storage without enforcing restrictive modes: ```bash PALEST_INK_DIR="$HOME/.palest-ink" mkdir -p "$PALEST_INK_DIR"/{data,reports,hooks,bin,tmp} ``` Foreground window titles are also stored in full: ```python record = { "ts": now_str, "type": "app_focus", "source": "app_collector", "data": { "app_name": app_name, "window_title": window_title, "duration_seconds": 15, } } with open(datafile, "a") as f: f.write(json.dumps(record, ensure_ascii=False) + "\n") ``` ### Technical Analysis The defaul ...[truncated 2056 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
collectors/install.sh:166
Finding

Installation Encourages Broad Terminal Privacy Permissions for Default Collectors

Content
View full analysis
/dev/null; then warn "Cannot access Safari history. Please grant Full Disk Access to Terminal:" warn " System Settings > Privacy & Security > Full Disk Access > Terminal.app" else rm -f "$PALEST_INK_DIR/tmp/safari_test.db" info "Safari history access: OK" fi fi warn "" warn "App Focus Tracking requires Accessibility permission:" warn " System Settings > Privacy & Security > Accessibility > Terminal.app (enable)" warn "Without this, collect_app.py will not be able to detect the frontmost app." ``` ### Technical Analysis Safari history and foreground-window tracking are declared features, and macOS privacy controls may require user approval. However, the guidance grants Full Disk Access and Accessibility to `Terminal.app`, not to a narrowly scoped, signed helper. Those permissions consequently apply to every command and script launched through that terminal application, not only Palest Ink. This exceeds the minimum process boundary needed for the Skill's reporting functionality and significantly increases the impact of the Git-hook injection vulnerability or any unrelated malicious terminal command. The installer also enables the affected collectors before obtaining separate informed consent for ...[truncated 1250 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (75)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README describes broad, automatic collection of highly sensitive activity data including browser history, shell commands, app focus, file changes, and page content summaries, but does not prominently warn users about the privacy and security implications. This is dangerous because users may enable persistent surveillance-like collection without informed consent, potentially capturing credentials, proprietary code context, internal URLs, or other sensitive work activity.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose is activity recall, but the skill also includes retention cleanup and deletion operations that change or remove user data. Hidden or weakly signposted destructive behavior in a recall-oriented skill creates a trust boundary violation: users may invoke it expecting read-only assistance while the skill also contains mechanisms to delete stored records.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared purpose is activity recall, but the skill also includes retention cleanup and deletion operations that change or remove user data. Hidden or weakly signposted destructive behavior in a recall-oriented skill creates a trust boundary violation: users may invoke it expecting read-only assistance while the skill also contains mechanisms to delete stored records.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared purpose is activity recall, but the skill also includes retention cleanup and deletion operations that change or remove user data. Hidden or weakly signposted destructive behavior in a recall-oriented skill creates a trust boundary violation: users may invoke it expecting read-only assistance while the skill also contains mechanisms to delete stored records.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared purpose is activity recall, but the skill also includes retention cleanup and deletion operations that change or remove user data. Hidden or weakly signposted destructive behavior in a recall-oriented skill creates a trust boundary violation: users may invoke it expecting read-only assistance while the skill also contains mechanisms to delete stored records.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The trigger rules are extremely broad, covering common requests like summaries, recent activity, browsing history, and vague references to prior work. Overbroad auto-triggering is dangerous here because the skill accesses highly sensitive local history and can run shell-based tooling, so it may be invoked in contexts where the user did not intend to reveal or process private activity data.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill handles exceptionally sensitive data categories—web history, shell commands, editor activity, app focus, and file changes—but presents them without an upfront privacy warning or consent framing. In context, this makes the skill more dangerous because users may trigger it casually without understanding the breadth of surveillance-like data being queried and summarized.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The collector explicitly allows tracking changes to .env files, which commonly contain secrets such as API keys, tokens, and database credentials. In the context of an activity-tracking skill that records user work history, monitoring and storing metadata about secret-bearing files increases the chance of credential exposure, sensitive project discovery, and downstream leakage through logs or summaries.

Content

Scanner excerpt · collectors/collect_fsevent.py (reported line 133)May include surrounding context.

python
# Skip binary-like files and hidden system files
        filename = os.path.basename(filepath)
        if filename.startswith(".") and filename not in {".env", ".gitignore", ".eslintrc"}:
            continue

        workspace = find_workspace(filepath)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

This script silently runs multiple collectors over highly sensitive user activity sources, including browser history, shell commands, VS Code edits, git activity, app focus, and filesystem events, without any user-facing notice, consent check, or gating in the collection path. In the context of an activity-tracking skill, this creates significant privacy and surveillance risk because it continuously aggregates broad behavioral data that could expose credentials, proprietary work, personal browsing, and other sensitive information if misused or accessed by an attacker.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The post-commit hook automatically captures repository path, branch, commit hash, commit message, changed files, and diff statistics, then writes them to a per-user log file without any runtime disclosure or consent. In this skill’s context, that is especially sensitive because commit messages, repo names, and filenames often contain proprietary project names, ticket numbers, credentials references, or other confidential work metadata, creating a stealthy local surveillance trail.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

The remaining hooks log merge, checkout, and push metadata, including repository path, branch transitions, remote names, and remote URLs, again without any visible warning at execution time. This materially increases exposure because remote URLs may embed internal hostnames or usernames, and the aggregate activity log can reveal private workflows, codebase relationships, and development habits across projects.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The default configuration enables collection of browser history, shell activity, VS Code activity, app focus, Git hooks, content fetching, and filesystem events immediately. Because these sources can reveal sensitive work habits, credentials-adjacent commands, visited sites, and viewed content, enabling them by default without a strong warning or selective opt-in is dangerous for a tracking skill.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · collectors/install.sh (reported line 171)May include surrounding context.

sh
warn "Cannot access Safari history. Please grant Full Disk Access to Terminal:"
        warn "  System Settings > Privacy & Security > Full Disk Access > Terminal.app"
    else
        rm -f "$PALEST_INK_DIR/tmp/safari_test.db"
        info "Safari history access: OK"
    fi
fi

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · collectors/uninstall.sh (reported line 70)May include surrounding context.

sh
info "Data directory removed."
else
    # Only remove hooks and bin, keep data
    rm -rf "$PALEST_INK_DIR/hooks" "$PALEST_INK_DIR/bin"
    info "Hooks and scripts removed. Data preserved at $PALEST_INK_DIR/data/"
fi

Session Persistence

Medium
Category
Rogue Agent
Confidence
89% confidence
Finding

The installation process establishes persistent data collection through a launchd agent, global git hooks, and local storage under the user's home directory. This is risky because persistence mechanisms continuously monitor developer activity and can keep collecting sensitive data across sessions, increasing exposure if the machine, account, or collected files are later accessed by an attacker or misused by the tool itself.

Content

Scanner excerpt · README.md (reported line 53)May include surrounding context.

text

This will:
- Create `~/.palest-ink/` for storing activity data
- Write a default `config.json`
- Install git hooks globally (`post-commit`, `post-merge`, `post-checkout`, `pre-push`)
- Install a **launchd agent** that runs every 15 seconds (replaces cron)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill exposes powerful capabilities via Read, Glob, Grep, and Bash but does not declare a constrained tool scope or clear permission boundary. Because the workflow includes arbitrary shell execution and access to sensitive local activity data, the lack of explicit scoping increases the chance of overbroad file access, command execution, and privacy-impacting behavior beyond the user’s immediate request.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

A skill framed as an activity recall/reporting tool also documents a workflow for deleting stored activity logs. Even though it asks for confirmation before force cleanup, combining sensitive-history recall with deletion in one skill raises the risk of accidental or socially engineered data loss, especially because users may not expect destructive maintenance features in this context.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The data-deletion capability is not necessary for the core purpose of answering questions about past activity, so it expands the attack surface without a strong functional justification. Any unnecessary destructive feature in a skill handling sensitive logs increases the consequences of prompt injection, misuse, or operator error.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · collectors/cleanup.py (reported line 12)May include surrounding context.

python
python3 cleanup.py --dry-run         # Show what would be deleted, no changes
    python3 cleanup.py --max-size 1.5    # Custom threshold in GB
    python3 cleanup.py --keep-days 60    # Always keep the most recent N days
    python3 cleanup.py --force           # Skip confirmation prompt (for skill use)
"""

import argparse

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · collectors/cleanup.py (reported line 99)May include surrounding context.

python
python3 cleanup.py --dry-run         # Show what would be deleted, no changes
    python3 cleanup.py --max-size 1.5    # Custom threshold in GB
    python3 cleanup.py --keep-days 60    # Always keep the most recent N days
    python3 cleanup.py --force           # Skip confirmation prompt (for skill use)
"""

import argparse

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 · collectors/collect_app.py (reported line 55)May include surrounding context.

python
return frontApp & "|||" & winTitle
'''
    try:
        result = subprocess.run(
            ["osascript", "-e", script],
            capture_output=True, text=True, timeout=3
        )

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The collector persistently stores foreground application names and window titles to ~/.palest-ink/data, which can capture highly sensitive user activity such as document names, websites, tickets, chats, or secrets shown in titles. In the context of an activity-tracking skill, this behavior is functionally intended, but without clear runtime consent, disclosure, retention limits, or protection of the stored data, it creates a meaningful privacy and surveillance risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The collector reads Chrome's History SQLite database and persists detailed browsing records, including URLs, titles, timestamps, and durations, into local JSONL files under the user's home directory without any visible consent, notice, or access-control safeguards in this code path. In a skill specifically designed to track user activity, this behavior is expected functionally, but it still creates a real privacy/security risk because highly sensitive browsing data is being continuously harvested and retained in a second location that may be easier for other local processes or users to access.

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 · collectors/collect_fsevent.py (reported line 69)May include surrounding context.

python
def find_changed_files(watch_dir, marker_path):
    """Use find -newer to get files changed since marker mtime."""
    try:
        result = subprocess.run(
            [
                "find", watch_dir,
                "-newer", marker_path,

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 · collectors/collect_git.py (reported line 60)May include surrounding context.

python
def run_git(repo_path, args):
    """Run a git command in the specified repo."""
    try:
        result = subprocess.run(
            ["git"] + args,
            cwd=repo_path,
            capture_output=True,

Static analysis

No suspicious patterns detected.