Back to skill

Security audit

Bohrium Job Management

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent for Bohrium job management, but it asks users to run an unverified remote installer and exposes destructive job actions and sensitive token-bearing API flows without enough safeguards.

Install only if you trust the Bohrium installer source and are comfortable giving the skill access to your Bohrium access key and project. Before using destructive actions such as kill or delete, confirm the exact job or job-group IDs and understand that results or records may be removed. Avoid printing or sharing API responses that include tokens, and be cautious running the batch helper on shared machines because it writes a predictable temporary file.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T03 · Remote Payload Retrieval and Execution

Error
Location
SKILL.md:33
Finding

Unverified Remote Installer Is Downloaded and Executed Directly

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 33–36
Vulnerability Type: T03: Remote Payload Retrieval and Execution
Risk Level: Critical

Vulnerable Code

bash
# macOS
/bin/bash -c "$(curl -fsSL https://dp-public.oss-cn-beijing.aliyuncs.com/bohrctl/1.0.0/install_bohr_mac_curl.sh)"

# Linux
/bin/bash -c "$(curl -fsSL https://dp-public.oss-cn-beijing.aliyuncs.com/bohrctl/1.0.0/install_bohr_linux_curl.sh)"

Technical Analysis

The installation instructions retrieve shell scripts from an external object-storage URL and pass the returned content directly to Bash. The downloaded payload is not authenticated with a publisher signature or checked against a pinned cryptographic digest before execution.

Although HTTPS protects the connection in transit under normal conditions, it does not protect users if the hosting account, stored object, publishing process, or delivery infrastructure is compromised. The effective code can also be changed after the Skill package has been audited without modifying any local project file.

Attack Path

  1. An attacker compromises the remote storage object, its publisher account, or the associated delivery infrastructure.
  2. The attacker replaces one of the installer scripts with a malicious shell payload.
  3. A user or agent follows the documented prerequisite command.
  4. curl downloads the modified content.
  5. Command substitution passes that content directly to /bin/bash.
  6. The payload executes with the privileges and environment of the invoking user.

Impact Assessment

Successful exploitation provides arbitrary command execution with the invoking user's privileges. The payload could read accessible files and environment variables, including Bohrium credentials, modify user-owned files, install persistence where permissions permit, replace local tools, or submit and manage remote compute jobs using the victim's account.

The scope is the user's local account and every external ser ...[truncated 160 chars]

Remediation
View remediation

Remediation Suggestions

  1. Do not pipe or interpolate remote content directly into a shell.
  2. Distribute the CLI through a signed, trusted package repository where possible.
  3. If a standalone installer is required:
    • Download it to a newly created local file.
    • Publish a version-specific SHA-256 digest through a separate trusted channel.
    • Verify the digest before execution.
    • Verify a publisher signature using a pinned public key.
    • Abort installation if either check fails.
  4. Pin an immutable release artifact rather than relying on a remotely mutable script.
  5. Instruct users to inspect the verified local script before running it.
  6. Avoid running the installer as root unless strictly necessary, and document its expected filesystem and network effects.

A safer workflow would resemble:

bash
curl -fL -o install_bohr_linux.sh \
  https://example.invalid/releases/bohr-1.0.0/install_bohr_linux.sh

printf '%s  %s\n' 'PINNED_SHA256_VALUE' 'install_bohr_linux.sh' |
  sha256sum --check -

# Verify a publisher signature here as well.
bash install_bohr_linux.sh

T09 · Insecure Skill Coding Practices

Warning
Location
batch_submit.py:103
Finding

Predictable Shared Temporary File Allows Symlink Overwrite and Configuration Races

Content
View full analysis

Vulnerability Details

File Location: batch_submit.py, lines 103–105
Vulnerability Type: T09: Insecure Skill Coding Practices
Risk Level: Medium

Vulnerable Code

python
tmp_json = Path("/tmp/bohrium_batch_job.json")
with open(tmp_json, "w") as f:
    json.dump(config, f, indent=2)

Technical Analysis

The script always writes the generated job configuration to the same predictable path in the shared /tmp directory. The file is opened with normal write mode, which follows symbolic links and truncates an existing target. The implementation does not use exclusive creation, symlink protection, a per-invocation randomized filename, explicit restrictive permissions, or cleanup.

On a multi-user system, another local user can pre-create /tmp/bohrium_batch_job.json as a symbolic link to a file writable by the victim. When the victim runs the script, Python follows the link and overwrites the linked target. Concurrent legitimate runs can also overwrite each other's temporary configuration, causing jobs to be submitted with the wrong project or template settings.

Attack Path

  1. A local attacker identifies a file that the victim can write and that would cause harm if replaced or truncated.
  2. The attacker creates a symbolic link at /tmp/bohrium_batch_job.json pointing to that target.
  3. The victim invokes batch_submit.py.
  4. open(tmp_json, "w") follows the symbolic link and truncates the target.
  5. The script writes the generated JSON into the target file.
  6. Alternatively, an attacker or concurrent process can replace the temporary JSON between its creation and its use by the bohr command, influencing submitted job configuration.

Exploitation requires local access to the same host and sufficient permissions to create entries in /tmp. The overwrite target must be writable by the victim process.

Impact Assessment

The direct impact is truncation or replacement of files writable by the invoking user. This can cau ...[truncated 455 chars]

Remediation
View remediation

Remediation Suggestions

  1. Use Python's tempfile module to create a unique file securely.
  2. Keep the temporary file owner-readable and owner-writable only.
  3. Ensure cleanup occurs in a finally block, including when submission fails.
  4. Do not reopen a predictable path after securely selecting a filename.
  5. If supported by the CLI, pass configuration through standard input and avoid a temporary file entirely.
  6. Prevent untrusted local processes from replacing the file before bohr reads it.

For example:

python
import json
import os
import tempfile
from pathlib import Path

tmp_path = None
try:
    with tempfile.NamedTemporaryFile(
        mode="w",
        prefix="bohrium_batch_",
        suffix=".json",
        delete=False,
        encoding="utf-8",
    ) as tmp:
        os.chmod(tmp.name, 0o600)
        json.dump(config, tmp, indent=2)
        tmp_path = Path(tmp.name)

    # Submit jobs using tmp_path.
finally:
    if tmp_path is not None:
        tmp_path.unlink(missing_ok=True)

For stronger resistance to replacement races, retain and consume an open file descriptor where the downstream interface permits it, or place the file inside a private TemporaryDirectory with mode 0700.

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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (12)

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The documented API response includes a file access token, which is credential material that could enable access to job files or related storage resources. Including credential-retrieval guidance in a broadly scoped operational skill increases the chance of accidental disclosure, misuse by an agent, or exploitation through prompt-induced overreach.

Content

Scanner excerpt · SKILL.md (reported line 322)May include surrounding context.

md
r = requests.get(f"{BASE}/job/list", headers=HEADERS,
    params={"page": 1, "pageSize": 10, "status": 1})

# Job config (includes file access token)
r = requests.get(f"{BASE}/job/view/conf/{job_id}", headers=HEADERS)
# Returns: {state, baseDir, tempDir, token, host, expires}

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill exposes an endpoint that returns job configuration along with a file access token, which materially exceeds ordinary job-status management needs. Surfacing token-retrieval guidance increases the risk of credential leakage, unauthorized file access, or abuse of downstream storage interfaces.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill documents shell execution and file-writing behaviors but does not declare any explicit tool scope or permission boundaries. That omission weakens least-privilege controls and makes it easier for an agent to invoke powerful actions without clear policy gating or user visibility.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill documents destructive commands such as delete and kill without requiring or strongly advising confirmation. In an agent setting, that creates a meaningful risk of accidental irreversible job/result destruction from misinterpretation, prompt injection, or user ambiguity.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The manifest limits the skill to compute job operations and explicitly excludes project management, yet the skill documents creating and managing job groups and repeatedly requires project IDs for those operations. While related to jobs, job-group creation and project-scoped organization go beyond the narrowly stated scope of submit/list/kill/delete/check logs/monitor status.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The API supplement introduces rename/modify capabilities beyond the skill's declared use cases, creating hidden functionality and widening the action surface available to the agent. Undeclared state-changing operations are dangerous because users and policy systems may not anticipate or constrain them.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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 · SKILL.md (reported line 330)May include surrounding context.

md
r = requests.get(f"{BASE}/job/{job_id}/snapshot", headers=HEADERS)

# Rename job
requests.post(f"{BASE}/job/{job_id}/modify",
    headers={**HEADERS, "Content-Type": "application/json"},
    json={"name": "new-name"})

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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 · SKILL.md (reported line 335)May include surrounding context.

json={"name": "new-name"})

Rename job group

requests.post(f"{BASE}/job_group/{job_group_id}/modify", headers={**HEADERS, "Content-Type": "application/json"}, json={"name": "new-group-name"})

text

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 · batch_submit.py (reported line 18)May include surrounding context.

python
def create_job_group(name: str, project_id: int) -> str | None:
    """Create a job group and return the group ID."""
    result = subprocess.run(
        ["bohr", "job_group", "create", "-n", name, "-p", str(project_id)],
        capture_output=True,
        text=True,

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 · batch_submit.py (reported line 51)May include surrounding context.

python
cmd = ["bohr", "job", "list", "-n", "20", "--json"]
    if status_flag:
        cmd.append(status_flag)
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
        return []
    try:

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 · poll_jobs.py (reported line 23)May include surrounding context.

python
cmd = ["bohr", "job", "list", "-n", "20", "--json"]
    if status_flag:
        cmd.append(status_flag)
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
        return []
    try:

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

Writing the modified job configuration to a predictable fixed path in /tmp creates a race and symlink attack surface on multi-user systems. Another local user could pre-create or replace /tmp/bohrium_batch_job.json to read sensitive job metadata, interfere with submissions, or cause the script to overwrite an unintended file.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.