Back to skill

Security audit

Openclaw Sentry

Security checks for vulnerabilities and agentic risk

Overview

The skill is a local secret scanner, but it also ships under-disclosed file-changing commands with weak workspace containment and unsafe plaintext backups.

Install only if you want a local workspace secret scanner and are prepared to control which commands agents run. Prefer using scan, check, and status. Treat redact, quarantine, unquarantine, defend, and protect as high-impact operations: run them only on trusted workspace-relative paths, review backups and quarantine contents, and rotate any credential that was ever exposed.

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 (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/sentry.py:482
Finding
Unvalidated file paths permit operations outside the selected workspace<![CDATA[ ## Vulnerability Details **File Location**: `scripts/sentry.py:482-695` **Vulnerability Type**: Path traversal and workspace-boundary violation **Risk Level**: High ### Vulnerable Code The redaction command constructs a target from an unvalidated user-controlled path: ```python def _redact_file(filepath, workspace): """Redact secrets in a single file. Returns (num_redacted, findings).""" try: content = filepath.read_text(encoding="utf-8", errors="ignore") except (OSError, PermissionError): return 0, [] # Secret matching and replacement occur here. if total_redacted > 0: # Create .bak backup before modifying bak = filepath.with_suffix(filepath.suffix + ".bak") shutil.copy2(filepath, bak) # Write redacted content filepath.write_text("\n".join(new_lines), encoding="utf-8") return total_redacted, findings ``` ```python if filepath: fpath = workspace / filepath if not fpath.exists(): print(f"File not found: {filepath}") return 1 if is_binary(fpath): print(f"Skipping binary file: {filepath}") return 0 count, findings = _redact_file(fpath, workspace) ``` The quarantine and restoration commands use the same unsafe path construction: ```python def cmd_quarantine(workspace, filepath): """Move a file containing secrets to quarantine with metadata.""" fpath = workspace / filepath if not fpath.exists(): print(f"File not found: {filepath}") return 1 # Scan the file first findings = [] if not is_binary(fpath): findings = scan_file(fpath, workspace) # Create quarantine directory qdir = quarantine_base(workspace) qdir.mkdir(parents=True, exist_ok=True) # Determine quarantine destination (preserve relative structure) rel = Path(filepath) dest = qdir / rel dest.parent.mkdir(parents=True, exist_ok=True) # Move file to quarantine shutil.move(str(fpa ...[truncated 2898 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Resolve the workspace once and validate every target before any operation: ```python def resolve_workspace_file(workspace, user_path): workspace = workspace.resolve(strict=True) supplied = Path(user_path) if supplied.is_absolute() or ".." in supplied.parts: raise ValueError("File path must be workspace-relative") target = (workspace / supplied).resolve(strict=False) try: target.relative_to(workspace) except ValueError: raise ValueError("File path escapes the workspace") return target ``` 2. Apply equivalent containment checks independently to: - Redaction targets. - Quarantine source and destination paths. - Unquarantine source and restoration paths. - Backup paths and metadata paths. 3. Validate the resolved path again immediately before mutation to reduce time-of-check/time-of-use and symlink-switching risks. 4. Reject symlinks for mutating commands, or securely verify that every resolved symlink target remains inside the allowed root. 5. Require explicit confirmation before moving private keys, environment files, or other operational credentials. 6. Add automated tests for: - `../` traversal. - Nested traversal. - Absolute Unix and Windows paths. - Symlinks pointing outside the workspace. - Quarantine and restoration paths that escape their respective roots. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/sentry.py:525
Finding
Redaction leaves original secrets in predictable plaintext backup files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/sentry.py:525-528` **Vulnerability Type**: Plaintext sensitive-data retention **Risk Level**: Medium ### Vulnerable Code ```python if total_redacted > 0: # Create .bak backup before modifying bak = filepath.with_suffix(filepath.suffix + ".bak") shutil.copy2(filepath, bak) # Write redacted content filepath.write_text("\n".join(new_lines), encoding="utf-8") ``` ### Technical Analysis Before replacing detected credentials, the program copies the complete original file to a predictable `<filename>.bak` location. This backup retains all original credentials in plaintext. The backup is placed adjacent to the source file and is not protected with explicitly restrictive permissions. Although `copy2` commonly preserves source metadata, the implementation does not verify the resulting permissions or account for platform-specific behavior. It also does not use exclusive creation, so an existing backup can be overwritten. The generated `.gitignore` patterns do not include a general `*.bak` rule. Consequently, a user may believe redaction removed credentials while the unredacted data remains available for accidental version-control commits, indexing, synchronization, or later workspace scans. ### Attack Path 1. A workspace file contains a credential matching one of the scanner's regular expressions. 2. The user runs: ```bash python3 scripts/sentry.py redact sensitive.conf --workspace /path/to/workspace ``` 3. The original content is copied to `sensitive.conf.bak`. 4. Only `sensitive.conf` is redacted. 5. The plaintext credential remains recoverable from `sensitive.conf.bak`. 6. The backup may subsequently be committed, synchronized, indexed, or read by another local process with access to the workspace. ### Impact Assessment This behavior undermines the confidentiality objective of redaction. Any secret in the original file remains exposed with the same substantive secu ...[truncated 545 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not create plaintext backups by default. Make backups an explicit opt-in option such as `--backup`. 2. Prefer atomic replacement: - Write redacted content to a securely created temporary file in the same directory. - Set restrictive permissions. - Flush and synchronize the file as appropriate. - Atomically replace the original only after successful validation. 3. If backups are required: - Store them in a dedicated protected directory outside version control. - Create them with exclusive semantics to prevent silent overwrites. - Restrict permissions to the current user, such as mode `0600` on supported systems. - Encrypt backup contents using an appropriately managed key. - Define and enforce a deletion or retention policy. - Clearly warn that the backup still contains live credentials. 4. Add backup locations or `*.bak` to generated `.gitignore` rules, while recognizing that ignore rules do not provide confidentiality. 5. Tell users to rotate every exposed credential even after redaction because local removal does not invalidate previously exposed secrets. 6. Add tests confirming that default redaction does not leave an unredacted copy anywhere in the workspace. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (31)

Credential Access

High
Category
Privilege Escalation
Content
## What It Detects

- **AWS** — Access keys (AKIA...), secret access keys
- **GitHub** — Personal access tokens (ghp_, gho_, ghs_, ghr_, github_pat_)
- **Slack** — Bot/user tokens (xox...), webhook URLs
- **Stripe** — Secret keys (sk_live_), publishable keys (pk_live_)
- **OpenAI** — API keys (sk-...)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- **Private Keys** — PEM files, .key/.pem/.p12/.pfx extensions
- **Database URLs** — PostgreSQL, MySQL, MongoDB, Redis with credentials
- **JWT Tokens** — JSON Web Tokens in plain text
- **Environment Files** — .env files with variables
- **.gitignore gaps** — Missing patterns for common secret files
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- **Private Keys** — PEM files, .key/.pem/.p12/.pfx extensions
- **Database URLs** — PostgreSQL, MySQL, MongoDB, Redis with credentials
- **JWT Tokens** — JSON Web Tokens in plain text
- **Environment Files** — .env files with variables
- **.gitignore gaps** — Missing patterns for common secret files
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- **Private Keys** — PEM files, .key/.pem/.p12/.pfx extensions
- **Database URLs** — PostgreSQL, MySQL, MongoDB, Redis with credentials
- **JWT Tokens** — JSON Web Tokens in plain text
- **Environment Files** — .env files with variables
- **.gitignore gaps** — Missing patterns for common secret files
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- **Private Keys** — PEM files, .key/.pem/.p12/.pfx extensions
- **Database URLs** — PostgreSQL, MySQL, MongoDB, Redis with credentials
- **JWT Tokens** — JSON Web Tokens in plain text
- **Environment Files** — .env files with variables
- **.gitignore gaps** — Missing patterns for common secret files
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- **Private Keys** — PEM files, .key/.pem/.p12/.pfx extensions
- **Database URLs** — PostgreSQL, MySQL, MongoDB, Redis with credentials
- **JWT Tokens** — JSON Web Tokens in plain text
- **Environment Files** — .env files with variables
- **.gitignore gaps** — Missing patterns for common secret files
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- **Private Keys** — PEM files, .key/.pem/.p12/.pfx extensions
- **Database URLs** — PostgreSQL, MySQL, MongoDB, Redis with credentials
- **JWT Tokens** — JSON Web Tokens in plain text
- **Environment Files** — .env files with variables
- **.gitignore gaps** — Missing patterns for common secret files
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- **Private Keys** — PEM files, .key/.pem/.p12/.pfx extensions
- **Database URLs** — PostgreSQL, MySQL, MongoDB, Redis with credentials
- **JWT Tokens** — JSON Web Tokens in plain text
- **Environment Files** — .env files with variables
- **.gitignore gaps** — Missing patterns for common secret files
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
| **Auto-redact secrets in files** | - | Yes |
| **Quarantine leaking skills** | - | Yes |
| **Generate .gitignore rules** | - | Yes |
| **Move .env to vault path** | - | Yes |

## Exit Codes
Confidence
88% confidence
Finding
The README advertises moving .env files to a vault path, which is a credential-handling action affecting highly sensitive files. In an agent workspace, automatically relocating .env files without strong safeguards can disrupt applications, accidentally expose secrets through incorrect destination handling, or enable unintended manipulation of credential stores.

Credential Access

High
Category
Privilege Escalation
Content
]

HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
]

HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
]

HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
]

HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
]

HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
]

HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
]

HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
}
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
}
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
}
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
}
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
}
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
}
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
}
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
}
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
HIGH_RISK_FILES = {
    ".env", ".env.local", ".env.production", ".env.staging", ".env.development",
    "credentials.json", "service-account.json", "secrets.json",
    ".npmrc", ".pypirc", ".netrc", ".pgpass", ".my.cnf",
    "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa",
}
Confidence
80% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Static analysis

No suspicious patterns detected.