T08 · Insecure Dependencies
- Location
SKILL.md:34- Finding
Unpinned Third-Party Installation Creates Supply-Chain Exposure
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This backup skill is not clearly malicious, but it needs Review because it can copy sensitive OpenClaw state in plaintext and restore or delete local files while its permissions and path scoping are under-disclosed and buggy.
Review carefully before installing. This skill is local-only in the reviewed scripts and I found no network upload, prompt hijacking, or intentional exfiltration, but it handles sensitive OpenClaw state in plaintext and can overwrite or delete local files. Use only after pinning the installed version, fixing path expansion and restore layout, constraining backupDir/watchFiles to intended OpenClaw paths, and treating cleanup/restore as destructive operations that need confirmation and a fresh backup.
SKILL.md:34Unpinned Third-Party Installation Creates Supply-Chain Exposure
config/backup-config.json:3Configured Home-Directory Paths Are Not Expanded
scripts/backup.py:101Nested Symbolic Links Are Followed During Directory Backup
scripts/restore.py:157Backup Archive Layout and Restore Destination Mapping Are Incompatible
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# 方法 1: 在 config/backup-config.json 中排除敏感文件
{
"excludePatterns": ["*.env", "*.key", "secrets/*"]
}
# 方法 2: 使用外部加密
The script accepts backupDir from a JSON config and then allows recursive deletion of matching backup-* files/directories without canonical-path validation or confinement to an expected base directory. Combined with --no-confirm, a tampered config can turn this into unattended destructive deletion of attacker-chosen paths, especially in cron or agent-driven contexts where no human reviews the target first.
parser.add_argument('--keep', type=int, help='保留最近 N 个备份')
parser.add_argument('--older-than', type=str, help='删除超过指定天数的备份 (如:30d)')
parser.add_argument('--dry-run', action='store_true', help='仅显示,不实际删除')
parser.add_argument('--no-confirm', action='store_true', help='跳过确认')
args = parser.parse_args()
print_header("🧹 清理备份")
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
This markdown file documents restore.py and cleanup.py, including commands that restore configurations and delete old backups, but it does not explicitly warn users about the potential for overwriting current configuration state or permanently removing backup files. Because these behaviors can affect user data and system integrity, the README should disclose them clearly.
The README documents restore commands that can overwrite active configuration files but does not warn users about that destructive side effect or recommend verifying the target version first. In a backup/restore skill, omission of overwrite warnings increases the chance of accidental data loss or rollback to an unsafe state, especially when users may run commands verbatim from the documentation.
The cleanup examples describe deletion operations without clearly warning that backups may be permanently removed. Because this skill is specifically for backup retention and recovery, undocumented destructive cleanup behavior can mislead users into deleting recoverable versions they may later need, resulting in irreversible loss of backup data.
The skill documents file read/write behavior but does not declare any explicit tool scope such as permissions or allowed-tools. This creates a transparency and least-privilege problem: an installer or host may not clearly understand that the skill can modify local files, including backups and restores under ~/.openclaw, increasing the chance of overbroad execution in a sensitive filesystem context.
The installation instructions reference 'npx clawhub' without pinning a specific version. Unpinned package execution can introduce supply-chain risk because future package updates, dependency compromise, or registry hijacking could cause different code to run than what was originally reviewed.
The skill encourages configuring a persistent scheduled task via system crontab, which establishes long-lived execution on the host. Persistence is not inherently malicious in a backup skill, but it is security-relevant because recurring unattended execution can amplify the impact of bugs, path mistakes, or later script tampering.
如需使用系统 cron:
crontab -e
# 添加:0 2 * * * cd ~/.openclaw/workspace/skills/auto-backup && python3 scripts/backup.py --note 定时备份
The documentation says only read access to ~/.openclaw/ is required, but the described operations create archives, restore files, and clean up backups, all of which require write access. Misstating required privileges can mislead reviewers and users, causing unsafe approvals or execution under broader access than expected.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
# 设置备份目录权限(推荐)
chmod 700 ~/.openclaw/backups
# 不要以 root 身份运行
# 以普通用户身份运行备份
This configuration enables automatic backups of multiple potentially sensitive workspace and identity files while explicitly disabling encryption. Although there is a note stating encryption is unsupported, the warning is not user-facing in any enforceable way and the backups are directed to local storage by default, which can expose secrets, session state, and personal data if the host is compromised or backups are shared.
The backup logic accepts config-supplied glob patterns and plain paths, then copies any matching file or directory from the local filesystem. Although the code skips top-level symlinks, it does not restrict sources to OpenClaw-owned configuration paths, so a modified or overly broad config can collect unrelated sensitive files such as SSH keys, shell history, or other application secrets into backup archives.
The script fully trusts backupDir and watchFiles from the JSON config, enabling config-driven collection of arbitrary files and directories and placement of backups in arbitrary writable locations. In the context of a configuration-backup skill, this is broader than necessary and increases the blast radius if the config is tampered with, because the skill can exfiltration-stage or persist copies of sensitive local data.
This code presents warnings, prompts, and argument descriptions in Chinese only, including the destructive-deletion confirmation flow. The policy requires avoiding forced language or locale behavior unless the user is given a choice or the constraint is clearly documented and justified.
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.
parser.add_argument('--keep', type=int, help='保留最近 N 个备份')
parser.add_argument('--older-than', type=str, help='删除超过指定天数的备份 (如:30d)')
parser.add_argument('--dry-run', action='store_true', help='仅显示,不实际删除')
parser.add_argument('--no-confirm', action='store_true', help='跳过确认')
args = parser.parse_args()
print_header("🧹 清理备份")
This code file contains multiple user-facing strings in Chinese, including the header, status messages, and usage hints. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is clearly documented and justified, which is not present here.
The main README content is written in Chinese, while English is relegated to a separate linked document rather than offering language choice inline. This can be interpreted as a language/locale policy issue if users are expected to consume the skill documentation in a specific language without explicit opt-in.
The manifest-level description emphasizes a fully self-contained local backup skill with '无网络' and '无外部依赖'. However, the same file advertises an external GitHub repository, which weakens the claimed self-contained/local-only framing of the skill package. This is a mild description mismatch because the documented operational scope is local-only while the distribution/source story includes an external dependency surface.
The natural-language note at L28 is written only in Chinese and does not indicate any language-selection or localization mechanism. This can violate language/locale policy when users are not explicitly opted into that locale.
The usage text and operational note are presented only in Chinese, and the rest of the script continues this pattern for user-visible output. Under the policy rule for natural-language violations, forcing a specific language without user opt-in can exclude users who do not read that language.
The top-level docstring presents core usage and security information in Chinese, including the restore description and security note, without indicating any language option or locale-specific justification. Under the policy, forcing a specific language without user opt-in is a natural-language policy issue.
No suspicious patterns detected.