Back to skill

Security audit

Journal Meta

Security checks for vulnerabilities and agentic risk

Overview

The skill performs the advertised paper lookup, but it can automatically find and run other local Python files by filename, which is a meaningful code-execution risk.

Review before installing. The network lookups are expected, but do not use confidential paper titles or private identifiers unless you are comfortable sending them to external metadata services. Avoid installing this alongside untrusted skills or plugins, and do not set JOURNAL_ABBREV_CLI or JOURNAL_IF_CLI to any script path you do not fully trust.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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)

T07 · Tool Hijacking and Spoofing

Error
Location
journal_meta.py:265
Finding

Automatic Discovery and Execution of Untrusted Local Python Tools

Content
View full analysis

Vulnerability Details

File Location: journal_meta.py, lines 265–321, with invocation points at lines 329–330 and 346–347
Vulnerability Type: Untrusted local tool discovery and execution
Risk Level: High

Vulnerable Code

python
def _find_sibling(basename, env_var):
    if basename in _SIBLING_CACHE:
        return _SIBLING_CACHE[basename]
    override = os.environ.get(env_var)
    if override and os.path.isfile(override):
        _SIBLING_CACHE[basename] = override
        return override
    here = os.path.dirname(os.path.abspath(__file__))
    roots = [
        here,
        os.path.dirname(os.path.dirname(here)),                       # <repo>/skills/journal-meta -> <repo>
        os.path.dirname(os.path.dirname(os.path.dirname(here))),      # workspace root (siblings live here)
        os.path.expanduser("~/.claude/skills"),
        os.path.expanduser("~/.config/openclaw/skills"),
        os.path.expanduser("~/.openclaw/skills"),
        os.path.expanduser("~/.claude/plugins"),
    ]
    found = None
    seen = set()
    for root in roots:
        if not root or root in seen or not os.path.isdir(root):
            continue
        seen.add(root)
        for dirpath, dirnames, filenames in os.walk(root):
            depth = dirpath[len(root):].count(os.sep)  # keep the walk shallow
            if depth > 5:
                dirnames[:] = []
                continue
            dirnames[:] = [d for d in dirnames if d not in (".git", "node_modules", "cache", "__pycache__", ".venv")]
            if basename in filenames:
                found = os.path.join(dirpath, basename)
                break
        if found:
            break
    _SIBLING_CACHE[basename] = found
    return found


def _call_cli(path, args, timeout=40):
    try:
        p = subprocess.run([sys.executable, path, *args, "--format", "json"],
                           capture_output=True, text=True, timeout=timeout)
    except (subprocess.TimeoutExpired, OSError):
    
...[truncated 3094 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove recursive filename-based discovery across workspace, Skill, and plugin trees.
  2. Require explicit configuration of sibling-tool paths, or resolve tools only from fixed installation directories controlled by the trusted package manager.
  3. Canonicalize configured paths with os.path.realpath() and verify that they remain within an allowlisted root.
  4. Reject symbolic links and files with unsafe ownership or permissions.
  5. Verify sibling tools using a pinned cryptographic hash, signed manifest, or authenticated package identity before execution.
  6. Avoid executing source files directly where possible. Prefer a trusted, versioned Python package with a documented API.
  7. Disable optional delegation by default when tool authenticity cannot be established; use the network fallback or require explicit user opt-in.
  8. Run optional enrichment tools in a restricted subprocess with a minimal environment, constrained filesystem access, no unnecessary network access, and resource limits.
  9. Validate subprocess output as untrusted data even after tool verification.
  10. If environment-variable overrides remain supported, clearly document that they are executable-code trust boundaries and apply the same path, ownership, permission, and integrity checks.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (9)

Lp1

High
Category
MCP Least Privilege
Confidence
95% confidence
Finding

This file makes multiple outbound HTTP requests to third-party services and reads environment variables, but those capabilities are not covered by declared permissions. That mismatch is dangerous because users may invoke a seemingly local metadata skill without realizing their queries and local configuration-derived data will be transmitted externally.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
95% confidence
Finding

This file makes multiple outbound HTTP requests to third-party services and reads environment variables, but those capabilities are not covered by declared permissions. That mismatch is dangerous because users may invoke a seemingly local metadata skill without realizing their queries and local configuration-derived data will be transmitted externally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README states that the skill queries external services such as OpenAlex and Crossref, but it does not clearly warn users that any DOI, PMID, arXiv ID, OpenAlex ID, or paper title they provide will be transmitted to third-party services. This creates a privacy and data-handling risk, especially when users submit unpublished manuscript titles, sensitive research topics, or identifiers that could reveal confidential work.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The helper appends an email address sourced from environment variables to outbound OpenAlex requests. Even if intended for polite-pool usage, this transmits potentially sensitive personal or organizational contact information to an external service without explicit user disclosure or consent.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · journal_meta.py (reported line 99)May include surrounding context.

python
# --------------------------------------------------------------------------- #
def openalex_fetch(id_type, value):
    """Return an OpenAlex work dict, or raise MetaError."""
    base = "https://api.openalex.org/works"
    try:
        if id_type == "doi":
            return _get_json("%s/https://doi.org/%s" % (base, urllib.parse.quote(value, safe="/")))

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · journal_meta.py (reported line 345)May include surrounding context.

python
# --------------------------------------------------------------------------- #
def openalex_fetch(id_type, value):
    """Return an OpenAlex work dict, or raise MetaError."""
    base = "https://api.openalex.org/works"
    try:
        if id_type == "doi":
            return _get_json("%s/https://doi.org/%s" % (base, urllib.parse.quote(value, safe="/")))

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · journal_meta.py (reported line 198)May include surrounding context.

python
# --------------------------------------------------------------------------- #
def crossref_fetch(doi):
    try:
        msg = _get_json("https://api.crossref.org/works/%s" % urllib.parse.quote(doi, safe="/"))["message"]
    except urllib.error.HTTPError as e:
        if e.code == 404:
            raise MetaError("not_found", "No paper matched DOI: %r" % doi, exit_code=3)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
84% confidence
Finding

The code executes another Python script whose path is discovered by walking sibling directories or taken from environment variables. Although subprocess.run is used without a shell, this still creates an execution boundary where a malicious or trojanized sibling skill can be invoked, leading to arbitrary code execution in the current agent context.

Content

Scanner excerpt · journal_meta.py (reported line 292)May include surrounding context.

python
def _call_cli(path, args, timeout=40):
    try:
        p = subprocess.run([sys.executable, path, *args, "--format", "json"],
                           capture_output=True, text=True, timeout=timeout)
    except (subprocess.TimeoutExpired, OSError):
        return None

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

文件使用自然语言将其描述为“一个 Claude Code 技能”,对使用环境作了单一平台表述。虽然末尾提到也兼容其他可运行 Python CLI 的代理,但开头的主描述仍可能被理解为对特定平台/环境的默认强约束,缺少显式的用户选择说明。

Content

No source excerpt is available for this finding.