Back to skill

Security audit

OneDrive Integration

Security checks for vulnerabilities and agentic risk

Overview

The skill is purpose-aligned for copying files to OneDrive, but it needs review because it ships a persistent machine-specific destination config and does not reliably constrain where copied files can be written.

Before installing, remove or replace the packaged config.env, confirm the active OneDrive root and subfolder, and avoid using absolute paths or .. in the subdir. This skill should add destination containment checks and safer file creation before it is used for sensitive documents or shared directories.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/copy_to_onedrive.py:96
Finding

Destination Path Escape Through Unvalidated Subdirectory

Content
View full analysis

Vulnerability Details

File Location: scripts/copy_to_onedrive.py, lines 96-100
Vulnerability Type: Unrestricted destination path / path traversal
Risk Level: Medium

python
subdir = args.subdir or cfg.get('ONEDRIVE_SUBDIR') or 'openclaw'

onedrive_root_p = Path(onedrive_root).expanduser()
dest_dir = onedrive_root_p / subdir

outs = []

Technical Analysis

The destination subdirectory can originate from the --subdir command-line argument or the ONEDRIVE_SUBDIR configuration value. The code joins this value to the configured OneDrive root without validating whether it is absolute or contains parent-directory components.

In pathlib, joining a path with an absolute second operand discards the first operand. Consequently, a value such as /tmp/output causes dest_dir to resolve outside the configured OneDrive root. A relative value containing traversal components, such as ../../target, can escape the root as well.

The subsequent copy_one() call creates the destination directory and writes the requested files there. The implementation therefore does not enforce its documented security boundary of copying only beneath ${ONEDRIVE_ROOT}/${ONEDRIVE_SUBDIR}.

Attack Path

  1. An attacker or untrusted caller supplies --subdir /tmp/attacker-target, --subdir ../../target, or places an equivalent value in config.env.
  2. The script constructs dest_dir without validating or resolving it against the configured OneDrive root.
  3. For an absolute value, pathlib discards onedrive_root_p; for a traversal value, the destination escapes through parent directories.
  4. copy_one() creates the escaped destination directory if necessary.
  5. The selected source files are copied to the attacker-selected location.

Impact Assessment

Exploitation permits directory creation and file placement anywhere writable by the account running the Skill, rather than only within the configured OneDrive ...[truncated 347 chars]

Remediation
View remediation

Remediation Suggestions

  • Reject absolute subdir values with Path(subdir).is_absolute().

  • Reject . and .. path components where they could alter the intended destination.

  • Resolve both paths and verify that the destination remains beneath the configured root:

    python
    root = Path(onedrive_root).expanduser().resolve()
    requested = Path(subdir)
    
    if requested.is_absolute() or '..' in requested.parts:
        raise SystemExit('ONEDRIVE_SUBDIR must be a safe relative path')
    
    dest_dir = (root / requested).resolve()
    try:
        dest_dir.relative_to(root)
    except ValueError:
        raise SystemExit('Destination must remain within ONEDRIVE_ROOT')
    
  • Apply the same validation regardless of whether the value originates from command-line arguments or configuration.

  • If nested subdirectories are unnecessary, restrict the value to a single safe directory name.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/copy_to_onedrive.py:33
Finding

Destination Symlink Following Enables Redirected File Writes

Content
View full analysis

Vulnerability Details

File Location: scripts/copy_to_onedrive.py, lines 33-51
Vulnerability Type: Symlink following and time-of-check/time-of-use race
Risk Level: Medium

python
def copy_one(src: Path, dest_dir: Path) -> Path:
    if not src.exists():
        raise FileNotFoundError(str(src))
    if src.is_dir():
        raise IsADirectoryError(str(src))

    dest_dir.mkdir(parents=True, exist_ok=True)
    out = dest_dir / safe_name(src)

    # Avoid overwrite by suffixing if needed
    if out.exists():
        stem = out.stem
        suf = out.suffix
        i = 2
        while True:
            cand = out.with_name(f"{stem}--{i}{suf}")
            if not cand.exists():
                out = cand
                break
            i += 1

    shutil.copy2(src, out)
    return out

Technical Analysis

The output path is checked with Path.exists() and later passed to shutil.copy2(). This does not safely protect against symbolic links.

A dangling symbolic link returns False from Path.exists(), so the code treats it as an unused destination. When shutil.copy2() opens that destination, the operating system follows the symbolic link and writes to its target. In addition, there is a time-of-check/time-of-use window between the existence check and the copy operation. An attacker able to modify the destination directory can replace a checked path with a symbolic link before copy2() opens it.

Output names are predictable because safe_name() deterministically derives them from source paths. This makes it practical for someone with write access to the destination directory to prepare the relevant symbolic link.

Attack Path

  1. An attacker has write access to the configured destination directory or can race modifications within it.
  2. The attacker determines the predictable sanitized output name for a source path.
  3. The attacker creates a dangling symbolic link ...[truncated 865 chars]
Remediation
View remediation

Remediation Suggestions

  • Explicitly reject symbolic links at candidate destinations using Path.is_symlink(), including dangling links.
  • Ensure the destination directory is not writable by untrusted users.
  • Avoid separate check-then-open operations. Create the destination atomically with exclusive and no-follow semantics, such as os.open() with O_CREAT | O_EXCL | O_WRONLY and O_NOFOLLOW where supported.
  • Copy data through the securely opened file descriptor rather than reopening the path with shutil.copy2().
  • Verify that the resolved destination parent remains beneath the trusted OneDrive root.
  • If timestamp preservation is required, apply metadata through descriptor-based operations after the content has been copied.
  • Handle collisions by attempting atomic exclusive creation and incrementing the suffix only when creation reports that the path already exists.
Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill explicitly instructs the agent to read environment-backed configuration, read arbitrary local files, and write files into both the skill config and the user's OneDrive, but it declares no tool scope or permission boundaries. That mismatch increases the chance the agent can perform broader filesystem actions than a reviewer or runtime policy expects, especially because the skill is designed to move potentially sensitive documents for sharing.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The onboarding flow tells the agent to persist machine-specific state by writing config.env, creating lasting configuration outside the immediate task. Persistent state can be abused or drift over time, causing future runs to use attacker-influenced paths or silently exfiltrate copied documents into an unintended OneDrive location if the config is tampered with.

Content

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

md
- `ONEDRIVE_ROOT` (required) — e.g. `/mnt/c/Users/<windows_user>/OneDrive`
- `ONEDRIVE_SUBDIR` (optional) — default `openclaw`

If config is missing/unset, do **not** guess—ask Boss to confirm the correct OneDrive folder, then write `config.env`.

## Initialization / installation / onboarding

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

python
dest_dir.mkdir(parents=True, exist_ok=True)
    out = dest_dir / safe_name(src)

    # Avoid overwrite by suffixing if needed
    if out.exists():
        stem = out.stem
        suf = out.suffix

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code performs a filesystem write by copying files into a destination under OneDrive, which can affect user data placement and synchronization behavior. Although the CLI arguments imply the purpose, the script provides no confirmation prompt or explicit user-facing warning before executing the copy operation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.