Back to skill

Security audit

Night Shift

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real queued coding automation skill, but its unattended runner gives child agents broad host access and has filesystem and verification weaknesses that require careful review.

Install only in a disposable or dedicated workspace first, with no production secrets in the environment. Do not use this on sensitive repositories or multi-user hosts unless you sandbox the child agent, restrict environment variables, review plans immediately before execution, and inspect diffs before merging.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (6)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/subagent_runner.py:108
Finding

Autonomous Agent Receives Trusted Tool Access and the Complete Host Environment

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/git_manager.py:59
Finding

Worktree Setup Recursively Weakens File Permissions and Changes Ownership

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/subagent_runner.py:102
Finding

Predictable Prompt Files Are Written Insecurely to the Shared Temporary Directory

Content
View full analysis
-.txt` as a symbolic link to another writable target. 3. Night Shift starts that phase. 4. `Path.write_text` follows the symbolic link and overwrites the target with the generated prompt. 5. Alternatively, the attacker reads the prompt while the delegated agent is running if its mode permits access. ### Impact Assessment The vulnerability may permit: - Disclosure of phase prompts and internal project information. - Overwriting arbitrary files writable by the Night Shift service account. - Interference with agent execution by replacing or modifying prompt content. - Leakage of paths and contextual information useful for further attacks. The practical impact depends on local account access and the service account's filesystem privileges. ]]>
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/executor.py:269
Finding

Failed Mechanical Verification Is Committed and Marked as Passed

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/git_manager.py:20
Finding

Unvalidated Persisted Plan IDs Reach Recursive Filesystem Deletion

Content
View full analysis
tuple[bool, str]: """Create an isolated git worktree for a plan. Returns (success, worktree_path).""" worktree_path = WORKTREES_DIR / plan_id branch = f"night-shift/{plan_id}" # Clean up existing worktree if present (must remove BEFORE deleting branch) if worktree_path.exists(): subprocess.run( ["git", "worktree", "remove", str(worktree_path), "--force"], cwd=WORKSPACE, capture_output=True, text=True, ) shutil.rmtree(worktree_path, ignore_errors=True) ``` ### Technical Analysis Newly generated IDs follow a restricted format, but deserialization overwrites the generated value with arbitrary `data["id"]`. No format, separator, absolute-path, or containment validation is performed. `WORKTREES_DIR / plan_id` permits traversal components such as `../` and permits an absolute path to replace the base path entirely. If the resulting path exists, the code attempts forced Git worktree removal and then calls `shutil.rmtree`. An attacker who can modify plan JSON or otherwise control persisted plan identifiers can therefore redirect destructive cleanup outside the intended worktree directory. ### Attack Path 1. An attacker o ...[truncated 1017 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/verifier.py:64
Finding

Unknown Verification Methods Succeed by Default

Content
View full analysis
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 (106)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description centers on workflow orchestration for coding plans and delayed execution in isolated worktrees. This code does not queue plans, approve them, execute work in worktrees, inspect reports, or manage runners. Instead, it provides runtime budget/accounting functionality for phases, plans, and nights, including API usage and persistence. While such budgeting could be a supporting component of a larger background execution system, this chunk’s primary behavior is materially different from the declared purpose and introduces undeclared capabilities related to budget tracking and disk persistence.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description focuses on plan queuing/approval, deferred execution in isolated worktrees, and report inspection. This code chunk does not implement those functions. Instead, its primary purpose is maintaining persistent failure memory for past runs, including storing structured failure metadata under the workspace data directory and using prompt hashes to detect repeated failures and skip retries. While this could be a supporting subsystem for a larger background execution tool, the behavior shown here is materially different from the declared user-facing purpose and introduces undeclared capabilities around persistent failure tracking and retry decisioning.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared description focuses on lifecycle management of plans: queueing, approval, deferred execution in isolated worktrees, and report inspection. This code chunk does not implement queue management, approval flows, execution scheduling, report inspection, or runner configuration. Instead, its primary function is generating structured phases and prompts for tasks. That is a materially different purpose from the declared description. While references to worktrees are loosely compatible with isolated execution, the substantive behavior here is automated plan/phase generation, including task-type detection and templates for cloning/analyzing external repos, extracting patterns, implementing skills, refactoring, and running tests. Those capabilities are undeclared, so this chunk is a description-behavior mismatch.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
98% confidence
Finding

Passing {**os.environ} to the router subprocess exposes all inherited environment variables, which may include API keys, tokens, and other secrets. Because the child is an external routing script that may call third-party providers, this broad secret propagation creates unnecessary credential exposure and potential exfiltration paths.

Content

Scanner excerpt · scripts/phase_runner.py (reported line 96)May include surrounding context.

python
capture_output=True,
            text=True,
            timeout=timeout + 30,
            env={**os.environ},
            cwd=worktree_path,
        )
        elapsed = time.time() - start

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% 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 · scripts/preflight.py (reported line 108)May include surrounding context.

python
then treat explicit auth errors as blockers. We intentionally do not run a
    paid/model task here.
    """
    env = {**os.environ, "HOME": os.environ.get("HOME", str(Path.home()))}
    probes = ([cli, "--version"], [cli, "--help"])
    last = ""
    for cmd in probes:

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
99% confidence
Finding

Passing the entire parent environment to a trusted autonomous agent exposes all available credentials, tokens, and internal configuration to a process whose behavior is driven by prompts and repository content. In an agent-execution skill, this is especially dangerous because prompt injection or malicious workspace files can steer the child process into reading and exfiltrating those secrets.

Content

Scanner excerpt · scripts/subagent_runner.py (reported line 120)May include surrounding context.

python
text=True,
            timeout=timeout + 30,
            cwd=worktree_path,
            env={**os.environ},
        )

        elapsed = time.time() - start

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% 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 · scripts/verifier.py (reported line 27)May include surrounding context.

python
"exec(": "Code execution",
        "__import__": "Dynamic imports",
        "compile(": "Code compilation",
        "rm -rf /": "Destructive file deletion",
        "rm -rf ~": "Home directory deletion",
        "dd if=": "Disk destruction",
        ":(){ :|:& };:": "Fork bomb",

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 · scripts/verifier.py (reported line 27)May include surrounding context.

python
"exec(": "Code execution",
        "__import__": "Dynamic imports",
        "compile(": "Code compilation",
        "rm -rf /": "Destructive file deletion",
        "rm -rf ~": "Home directory deletion",
        "dd if=": "Disk destruction",
        ":(){ :|:& };:": "Fork bomb",

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% 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 · scripts/verifier.py (reported line 28)May include surrounding context.

python
"__import__": "Dynamic imports",
        "compile(": "Code compilation",
        "rm -rf /": "Destructive file deletion",
        "rm -rf ~": "Home directory deletion",
        "dd if=": "Disk destruction",
        ":(){ :|:& };:": "Fork bomb",
        "chmod 777 /": "Root permission escalation",

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% 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 · scripts/verifier.py (reported line 31)May include surrounding context.

python
"rm -rf ~": "Home directory deletion",
        "dd if=": "Disk destruction",
        ":(){ :|:& };:": "Fork bomb",
        "chmod 777 /": "Root permission escalation",
        "mkfs.": "Filesystem formatting",
        "/dev/sda": "Direct disk access",
        "> /dev/sda": "Direct disk write",

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · INSTALL.md (reported line 22)May include surrounding context.

bash
export OPENCLAW_WORKSPACE=/tmp/night-shift-demo
mkdir -p "$OPENCLAW_WORKSPACE"
python3 ~/.openclaw/workspace/skills/night-shift/scripts/preflight.py --json
python3 ~/.openclaw/workspace/skills/night-shift/scripts/executor.py dry-run

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · INSTALL.md (reported line 35)May include surrounding context.

bash
cp skills/night-shift/.night-shift.env.example ~/.openclaw/workspace/.night-shift.env
chmod 600 ~/.openclaw/workspace/.night-shift.env

Then edit values for your environment. Do not commit real secrets.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% 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 · REFERENCE.md (reported line 419)May include surrounding context.

md
Do **not** market it like:
- “set and forget magic coding forever”
- “safe for any repo with zero setup”
- “works equally well without verification or review”

The real pitch is better:
> a structured autonomous execution framework for deferred engineering work

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill advertises powerful capabilities in metadata, including filesystem writes, git worktrees, subprocess execution, optional external CLIs, and inherited environment access, but it does not declare an explicit tool scope such as permissions or allowed-tools. That creates an authorization ambiguity where a host may expose more capability than users expect, which is especially risky for an unattended execution skill that queues and later runs approved work.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Using a common conversational phrase like "good night" as a trigger for starting queued execution can cause accidental invocation during ordinary chat, especially in multi-skill environments. Because this skill can later spawn subprocesses, mutate repositories, and run unattended workflows, an unintended trigger may initiate materially risky actions after prior approvals exist.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The bare trigger word "morning" is overly generic and may invoke reporting behavior unintentionally during normal conversation. The impact is lower than the execution trigger because it is read/report oriented, but it can still surface workspace status, plan details, or report content unexpectedly in the wrong context.

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 · scripts/checkpoint.py (reported line 90)May include surrounding context.

python
def _get_git_head(self, worktree_path: str) -> str:
        try:
            result = subprocess.run(
                ["git", "rev-parse", "HEAD"],
                cwd=worktree_path,
                capture_output=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 · scripts/checkpoint.py (reported line 103)May include surrounding context.

python
def _get_git_diff(self, worktree_path: str) -> str:
        try:
            result = subprocess.run(
                ["git", "diff", "--stat"],
                cwd=worktree_path,
                capture_output=True,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This executor intentionally runs previously approved phases that may invoke shell or subagent actions which mutate code and the workspace without a fresh confirmation gate at execution time. In the context of an agentic overnight runner, stale approval, plan tampering, or overly broad phase prompts can translate directly into unattended code execution and repository modification, making the operational risk substantially higher than in an interactive tool.

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 · scripts/executor.py (reported line 475)May include surrounding context.

python
def _check_memory(self) -> int:
        """Check available memory in bytes."""
        try:
            result = subprocess.run(
                ["awk", "/MemAvailable/ {print $2 * 1024}", "/proc/meminfo"],
                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 · scripts/executor.py (reported line 488)May include surrounding context.

python
def _check_swap(self) -> int:
        """Check total swap in bytes."""
        try:
            result = subprocess.run(
                ["awk", "/SwapTotal/ {print $2 * 1024}", "/proc/meminfo"],
                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 · scripts/executor.py (reported line 511)May include surrounding context.

python
cmd = [sys.executable, str(MEMORY_GUARD_SCRIPT)]
            if self.dry_run:
                cmd.append("--dry-run")
            self._memory_guard_proc = subprocess.Popen(
                cmd,
                stdout=subprocess.DEVNULL,
                stderr=subprocess.DEVNULL,

Tainted flow: 'EXECUTION_LOG' from os.environ.get (line 56, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
83% confidence
Finding

The execution log path is derived from OPENCLAW_WORKSPACE, which can come from the environment, and is later opened for append without validation. If an attacker can influence the environment when this skill runs, they can redirect log writes to arbitrary filesystem locations accessible to the process, causing clobbering, unauthorized file creation, or data leakage via misplaced logs.

Content

Scanner excerpt · scripts/executor.py (reported line 559)May include surrounding context.

python
def _save_log(self):
        """Save execution log to file."""
        EXECUTION_LOG.parent.mkdir(parents=True, exist_ok=True)
        with open(EXECUTION_LOG, "a") as f:
            f.write("\n".join(self.log_entries) + "\n")

    def _get_summary(self) -> str:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The stop path performs a process-termination operation using os.kill, which is a potentially disruptive system action. While the result is printed after the fact, there is no confirmation prompt or prior warning before terminating the process identified in the lock file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code persists failure metadata, including plan IDs, phase IDs, timestamps, details, and prompt-derived hashes, to a file under the workspace. There is no confirmation prompt, print/log disclosure, or comment/docstring near the write path informing users that their failure information will be stored on disk.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/queue.py:14

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/verifier.py:23