Back to skill

Security audit

Restic Home Backup (Safe Apply Mode)

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent restic backup helper, but its root-level setup script has unsafe configuration handling that could lead to command execution as root.

Review carefully before installing. Use only plan mode until the bootstrap script validates and safely quotes all inputs, avoids sourcing config as shell code, creates password files with restrictive permissions from the start, and adds least-privilege systemd settings.

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

Error
Location
scripts/bootstrap_restic_home.sh:98
Finding

Root Command Injection Through Shell-Sourced Configuration

Content
View full analysis
/etc/restic-home.env </dev/null 2>&1; then /usr/bin/restic init fi fi ``` ### Technical Analysis The values accepted through `--repo`, `--password-file`, and indirectly `--user` are inserted into `/etc/restic-home.env` without escaping or validation. Although systemd supports an `EnvironmentFile` format, the generated backup, prune, and check scripts do not parse the file strictly as systemd environment data. They execute: ```bash source /etc/restic-home.env ``` Consequently, the file is interpreted as shell code. An attacker-controlled argument containing a newline can append a new shell statement to the generated file. Shell metacharacters placed in a separate injected line will execute when the file is sourced. The bootstrap script is intended to be run with elevated privileges because it writes to `/etc`, `/usr/local/bin`, and `/etc/systemd/system`. The generated systemd services do not specify a less-privileged `User=`, so they run as root by default. This converts configuration injection into ...[truncated 1673 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/bootstrap_restic_home.sh:79
Finding

Password Generation Fallback Can Leave Repository Credentials Exposed

Content
View full analysis
/dev/null 2>&1; then openssl rand -base64 48 > "$PASS_FILE" else tr -dc 'A-Za-z0-9!@#$%^&*()-_=+[]{}:,.?' "$PASS_FILE" echo >> "$PASS_FILE" fi chmod 600 "$PASS_FILE" ``` ### Technical Analysis The script globally enables both `set -e` and `set -o pipefail`. In the fallback password-generation pipeline, `head -c 64` exits after receiving the required number of bytes. The upstream `tr` process may then receive `SIGPIPE` when it attempts to write additional output. With `pipefail` enabled, the pipeline can return a nonzero status because of the terminated `tr` process. With `set -e` enabled, the script can exit immediately before reaching: ```bash chmod 600 "$PASS_FILE" ``` The output redirection creates the password file before the pipeline starts. Its initial permissions therefore depend on the invoking process's umask. No restrictive `umask` is set before the secret is created. Under a common umask such as `0022`, the file may initially be created with permissions that allow other local users to read it. The risk is greater because `--password-file` is configurable and can identify a location outside the default `/etc/restic-home/` directory. ### Attack Path 1. The bootstrap script runs on a system where `openssl` is unavailable. 2. The script enters the `tr | head` fallback path. 3. Redirection creates the password file using permissions derived from the current umask. 4. `head` exits after reading 64 bytes. 5. `tr` receives `SIGPIPE`, causing the pipeline to return a nonzero status under `pipefail`. 6. `set -e` terminates the script before `chmod 600` executes. 7. A local user reads the partially or fully generated restic password if the file was created with permissive mode b ...[truncated 781 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (14)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill clearly contemplates shell-driven system changes, credential file creation, and systemd unit installation, but it declares no explicit tool scope or permissions boundary. That omission makes it easier for an agent runtime to overgrant execution capability or for reviewers to miss that the skill can modify sensitive paths like /etc and /usr/local/bin.

Content

No source excerpt is available for this finding.

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 · SKILL.md (reported line 30)May include surrounding context.

md
- Never print secrets or tokens in chat/log output.
  - Never delete snapshots/repositories without explicit user confirmation.
  - Never weaken permissions on credential files (`chmod 600` minimum).
  - Never claim backup success without checking command exit status and snapshot listing.
  - Never apply system changes implicitly: require explicit `--apply` (or explicit user confirmation) before writing to `/etc`, `/usr/local/bin`, or `/etc/systemd/system`.

## Workflow

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The publication workflow introduces unrelated packaging and registry actions into a backup-operation skill, expanding its operational scope beyond what a user would reasonably expect. This can cause an agent to perform supply-chain or external publication steps in contexts where the user only asked for local backup configuration, increasing the chance of unintended outbound actions or data exposure.

Content

No source excerpt is available for this finding.

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 · SKILL.md (reported line 29)May include surrounding context.

md
### Wrong password
Symptoms: `wrong password or no key found`
- Confirm `/etc/restic-home.env` points to correct `RESTIC_PASSWORD_FILE`.
- Confirm password file permissions (`chmod 600`).

### Repo unreachable
Symptoms: timeout / connection refused

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 · references/ops-checklist.md (reported line 24)May include surrounding context.

md
### Wrong password
Symptoms: `wrong password or no key found`
- Confirm `/etc/restic-home.env` points to correct `RESTIC_PASSWORD_FILE`.
- Confirm password file permissions (`chmod 600`).

### Repo unreachable
Symptoms: timeout / connection refused

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 · scripts/bootstrap_restic_home.sh (reported line 88)May include surrounding context.

sh
### Wrong password
Symptoms: `wrong password or no key found`
- Confirm `/etc/restic-home.env` points to correct `RESTIC_PASSWORD_FILE`.
- Confirm password file permissions (`chmod 600`).

### Repo unreachable
Symptoms: timeout / connection refused

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 · scripts/bootstrap_restic_home.sh (reported line 91)May include surrounding context.

sh
### Wrong password
Symptoms: `wrong password or no key found`
- Confirm `/etc/restic-home.env` points to correct `RESTIC_PASSWORD_FILE`.
- Confirm password file permissions (`chmod 600`).

### Repo unreachable
Symptoms: timeout / connection refused

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 · scripts/bootstrap_restic_home.sh (reported line 107)May include surrounding context.

sh
### Wrong password
Symptoms: `wrong password or no key found`
- Confirm `/etc/restic-home.env` points to correct `RESTIC_PASSWORD_FILE`.
- Confirm password file permissions (`chmod 600`).

### Repo unreachable
Symptoms: timeout / connection refused

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/bootstrap_restic_home.sh (reported line 11)May include surrounding context.

sh
#   bash bootstrap_restic_home.sh --user pi --repo /mnt/backup/restic-home
#
# Apply changes:
#   sudo bash bootstrap_restic_home.sh --user pi --repo /mnt/backup/restic-home --apply
#
# Optional:
#   --password-file /etc/restic-home/password

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/bootstrap_restic_home.sh (reported line 73)May include surrounding context.

sh
#   bash bootstrap_restic_home.sh --user pi --repo /mnt/backup/restic-home
#
# Apply changes:
#   sudo bash bootstrap_restic_home.sh --user pi --repo /mnt/backup/restic-home --apply
#
# Optional:
#   --password-file /etc/restic-home/password

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 · scripts/bootstrap_restic_home.sh (reported line 115)May include surrounding context.

sh
source /etc/restic-home.env
exec /usr/bin/restic backup "$BACKUP_SOURCE" --exclude-file "$EXCLUDES_FILE"
EOF
chmod 755 /usr/local/bin/restic-home-backup.sh

cat >/usr/local/bin/restic-home-prune.sh <<'EOF'
#!/usr/bin/env bash

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 · scripts/bootstrap_restic_home.sh (reported line 123)May include surrounding context.

sh
source /etc/restic-home.env
exec /usr/bin/restic backup "$BACKUP_SOURCE" --exclude-file "$EXCLUDES_FILE"
EOF
chmod 755 /usr/local/bin/restic-home-backup.sh

cat >/usr/local/bin/restic-home-prune.sh <<'EOF'
#!/usr/bin/env bash

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 · scripts/bootstrap_restic_home.sh (reported line 131)May include surrounding context.

sh
source /etc/restic-home.env
exec /usr/bin/restic backup "$BACKUP_SOURCE" --exclude-file "$EXCLUDES_FILE"
EOF
chmod 755 /usr/local/bin/restic-home-backup.sh

cat >/usr/local/bin/restic-home-prune.sh <<'EOF'
#!/usr/bin/env bash

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% 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/bootstrap_restic_home.sh (reported line 210)May include surrounding context.

sh
systemctl daemon-reload

if [[ "$ENABLE_TIMERS" == "yes" ]]; then
  systemctl enable --now restic-home-backup.timer restic-home-prune.timer restic-home-check.timer
fi

if [[ "$INIT_REPO" == "yes" ]]; then

Static analysis

No suspicious patterns detected.