Back to skill

Security audit

Hetzner

Security checks for vulnerabilities and agentic risk

Overview

This Hetzner operations skill is coherent and purpose-aligned, with local note storage and clear handling rules for credentials and destructive cloud actions.

Install only if you want an agent to help operate Hetzner infrastructure and maintain local Clawic inventories. It can guide actions that affect real cloud resources and costs, so confirm the active project/context before any write command and review destructive steps carefully. Do not paste raw secrets unless you expect the agent to replace them with pointers before saving notes.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (15)

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
**Hosts go to the shared inventory `~/Clawic/data/servers/servers.md`**, not into this skill's folder: one file holds machines from every provider, so "what am I paying for" answers itself whichever cloud they live in. One row per host, identified by `Name` + `Provider` (`hetzner`) — update your own row in place, never append a second one. Cloud servers and Robot dedicated servers are rows in the same table, told apart by `Type`. Domains and zones go to `~/Clawic/data/domains/domains.md` the same way, and a server that belongs to a client leaves the client in `~/Clawic/data/contacts/contacts.md` and only the client's name here.

**No credential is ever written anywhere under `~/Clawic/data/`** — not in the files named above, not in a file you create, not in text the user pastes in to be kept. A Hetzner API token, a rescue password, a Storage Box password, a WireGuard private key or a database password inside a cloud-init file gets replaced by its pointer before anything is written: `env:HCLOUD_TOKEN`, `keychain:hetzner-prod`, `1password:Infra/Hetzner/prod`, `file:~/.ssh/id_ed25519`.

Hetzner sells cheap compute and almost no managed services: the money saved on the invoice is spent on operations you now own. Quote the monthly figure in EUR, say plainly what Hetzner does not provide for a given design, and treat the project as the blast radius, because a single API token has no permission model inside it. Work from defaults immediately: never open with questions about their account, their budget or their location. The one exception to silence is `default_location` — while it is unset, state which location you are assuming before acting (Rule 7). That is a statement, not a question. Precedence for any value: `config.yaml` → `~/Clawic/profile.yaml` (shared universals: currency, locale) → the Configuration table default.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · memory-template.md (reported line 58)May include surrounding context.

md
**Hosts go to the shared inventory `~/Clawic/data/servers/servers.md`**, not into this skill's folder: one file holds machines from every provider, so "what am I paying for" answers itself whichever cloud they live in. One row per host, identified by `Name` + `Provider` (`hetzner`) — update your own row in place, never append a second one. Cloud servers and Robot dedicated servers are rows in the same table, told apart by `Type`. Domains and zones go to `~/Clawic/data/domains/domains.md` the same way, and a server that belongs to a client leaves the client in `~/Clawic/data/contacts/contacts.md` and only the client's name here.

**No credential is ever written anywhere under `~/Clawic/data/`** — not in the files named above, not in a file you create, not in text the user pastes in to be kept. A Hetzner API token, a rescue password, a Storage Box password, a WireGuard private key or a database password inside a cloud-init file gets replaced by its pointer before anything is written: `env:HCLOUD_TOKEN`, `keychain:hetzner-prod`, `1password:Infra/Hetzner/prod`, `file:~/.ssh/id_ed25519`.

Hetzner sells cheap compute and almost no managed services: the money saved on the invoice is spent on operations you now own. Quote the monthly figure in EUR, say plainly what Hetzner does not provide for a given design, and treat the project as the blast radius, because a single API token has no permission model inside it. Work from defaults immediately: never open with questions about their account, their budget or their location. The one exception to silence is `default_location` — while it is unset, state which location you are assuming before acting (Rule 7). That is a statement, not a question. Precedence for any value: `config.yaml` → `~/Clawic/profile.yaml` (shared universals: currency, locale) → the Configuration table default.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · memory-template.md (reported line 183)May include surrounding context.

md
**Hosts go to the shared inventory `~/Clawic/data/servers/servers.md`**, not into this skill's folder: one file holds machines from every provider, so "what am I paying for" answers itself whichever cloud they live in. One row per host, identified by `Name` + `Provider` (`hetzner`) — update your own row in place, never append a second one. Cloud servers and Robot dedicated servers are rows in the same table, told apart by `Type`. Domains and zones go to `~/Clawic/data/domains/domains.md` the same way, and a server that belongs to a client leaves the client in `~/Clawic/data/contacts/contacts.md` and only the client's name here.

**No credential is ever written anywhere under `~/Clawic/data/`** — not in the files named above, not in a file you create, not in text the user pastes in to be kept. A Hetzner API token, a rescue password, a Storage Box password, a WireGuard private key or a database password inside a cloud-init file gets replaced by its pointer before anything is written: `env:HCLOUD_TOKEN`, `keychain:hetzner-prod`, `1password:Infra/Hetzner/prod`, `file:~/.ssh/id_ed25519`.

Hetzner sells cheap compute and almost no managed services: the money saved on the invoice is spent on operations you now own. Quote the monthly figure in EUR, say plainly what Hetzner does not provide for a given design, and treat the project as the blast radius, because a single API token has no permission model inside it. Work from defaults immediately: never open with questions about their account, their budget or their location. The one exception to silence is `default_location` — while it is unset, state which location you are assuming before acting (Rule 7). That is a statement, not a question. Precedence for any value: `config.yaml` → `~/Clawic/profile.yaml` (shared universals: currency, locale) → the Configuration table default.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · memory-template.md (reported line 184)May include surrounding context.

md
**Hosts go to the shared inventory `~/Clawic/data/servers/servers.md`**, not into this skill's folder: one file holds machines from every provider, so "what am I paying for" answers itself whichever cloud they live in. One row per host, identified by `Name` + `Provider` (`hetzner`) — update your own row in place, never append a second one. Cloud servers and Robot dedicated servers are rows in the same table, told apart by `Type`. Domains and zones go to `~/Clawic/data/domains/domains.md` the same way, and a server that belongs to a client leaves the client in `~/Clawic/data/contacts/contacts.md` and only the client's name here.

**No credential is ever written anywhere under `~/Clawic/data/`** — not in the files named above, not in a file you create, not in text the user pastes in to be kept. A Hetzner API token, a rescue password, a Storage Box password, a WireGuard private key or a database password inside a cloud-init file gets replaced by its pointer before anything is written: `env:HCLOUD_TOKEN`, `keychain:hetzner-prod`, `1password:Infra/Hetzner/prod`, `file:~/.ssh/id_ed25519`.

Hetzner sells cheap compute and almost no managed services: the money saved on the invoice is spent on operations you now own. Quote the monthly figure in EUR, say plainly what Hetzner does not provide for a given design, and treat the project as the blast radius, because a single API token has no permission model inside it. Work from defaults immediately: never open with questions about their account, their budget or their location. The one exception to silence is `default_location` — while it is unset, state which location you are assuming before acting (Rule 7). That is a statement, not a question. Precedence for any value: `config.yaml` → `~/Clawic/profile.yaml` (shared universals: currency, locale) → the Configuration table default.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · security.md (reported line 51)May include surrounding context.

md
**Hosts go to the shared inventory `~/Clawic/data/servers/servers.md`**, not into this skill's folder: one file holds machines from every provider, so "what am I paying for" answers itself whichever cloud they live in. One row per host, identified by `Name` + `Provider` (`hetzner`) — update your own row in place, never append a second one. Cloud servers and Robot dedicated servers are rows in the same table, told apart by `Type`. Domains and zones go to `~/Clawic/data/domains/domains.md` the same way, and a server that belongs to a client leaves the client in `~/Clawic/data/contacts/contacts.md` and only the client's name here.

**No credential is ever written anywhere under `~/Clawic/data/`** — not in the files named above, not in a file you create, not in text the user pastes in to be kept. A Hetzner API token, a rescue password, a Storage Box password, a WireGuard private key or a database password inside a cloud-init file gets replaced by its pointer before anything is written: `env:HCLOUD_TOKEN`, `keychain:hetzner-prod`, `1password:Infra/Hetzner/prod`, `file:~/.ssh/id_ed25519`.

Hetzner sells cheap compute and almost no managed services: the money saved on the invoice is spent on operations you now own. Quote the monthly figure in EUR, say plainly what Hetzner does not provide for a given design, and treat the project as the blast radius, because a single API token has no permission model inside it. Work from defaults immediately: never open with questions about their account, their budget or their location. The one exception to silence is `default_location` — while it is unset, state which location you are assuming before acting (Rule 7). That is a statement, not a question. Precedence for any value: `config.yaml` → `~/Clawic/profile.yaml` (shared universals: currency, locale) → the Configuration table default.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
## Cloud Projects
| Project | Purpose | Environment | Token | Location | Notes |
|---------|---------|-------------|-------|----------|-------|
| acme-prod | main app | prod | keychain:hetzner-prod | fsn1 | read-write; CI uses a separate read-only token |

## Current Infrastructure
Network 10.10.0.0/16 in fsn1 · LB11 → 2× cax21 app · ccx13 postgres + 200 GB volume · Storage Box BX11 for Borg · dedicated AX41 (Robot) for CI, vSwitch into the network.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · memory-template.md (reported line 131)May include surrounding context.

md
## Cloud Projects
| Project | Purpose | Environment | Token | Location | Notes |
|---------|---------|-------------|-------|----------|-------|
| acme-prod | main app | prod | keychain:hetzner-prod | fsn1 | read-write; CI uses a separate read-only token |

## Current Infrastructure
Network 10.10.0.0/16 in fsn1 · LB11 → 2× cax21 app · ccx13 postgres + 200 GB volume · Storage Box BX11 for Borg · dedicated AX41 (Robot) for CI, vSwitch into the network.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · memory-template.md (reported line 185)May include surrounding context.

md
## Cloud Projects
| Project | Purpose | Environment | Token | Location | Notes |
|---------|---------|-------------|-------|----------|-------|
| acme-prod | main app | prod | keychain:hetzner-prod | fsn1 | read-write; CI uses a separate read-only token |

## Current Infrastructure
Network 10.10.0.0/16 in fsn1 · LB11 → 2× cax21 app · ccx13 postgres + 200 GB volume · Storage Box BX11 for Borg · dedicated AX41 (Robot) for CI, vSwitch into the network.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · memory-template.md (reported line 264)May include surrounding context.

md
## Cloud Projects
| Project | Purpose | Environment | Token | Location | Notes |
|---------|---------|-------------|-------|----------|-------|
| acme-prod | main app | prod | keychain:hetzner-prod | fsn1 | read-write; CI uses a separate read-only token |

## Current Infrastructure
Network 10.10.0.0/16 in fsn1 · LB11 → 2× cax21 app · ccx13 postgres + 200 GB volume · Storage Box BX11 for Borg · dedicated AX41 (Robot) for CI, vSwitch into the network.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · memory-template.md (reported line 265)May include surrounding context.

md
## Cloud Projects
| Project | Purpose | Environment | Token | Location | Notes |
|---------|---------|-------------|-------|----------|-------|
| acme-prod | main app | prod | keychain:hetzner-prod | fsn1 | read-write; CI uses a separate read-only token |

## Current Infrastructure
Network 10.10.0.0/16 in fsn1 · LB11 → 2× cax21 app · ccx13 postgres + 200 GB volume · Storage Box BX11 for Borg · dedicated AX41 (Robot) for CI, vSwitch into the network.

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
80% confidence
Finding

Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Content

Scanner excerpt · servers.md (reported line 38)May include surrounding context.

md
Rules that follow from the table:

- **Type availability is per location.** ARM (CAX) has historically been EU-only, and inventory for a given type runs out in a location without warning. Check availability in the target location before designing around a family, and have a second choice ready.
- **Private networks are per location.** Two servers in `fsn1` and `hel1` cannot share one; crossing locations means WireGuard or public endpoints (`network.md`).
- **Volumes are per location** and cannot be attached across them (`storage.md`).
- **`data_residency: eu`** removes `ash`, `hil` and `sin` from the options entirely — say so rather than quoting a US price the user cannot use.

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 251)May include surrounding context.

md
| Treating Backups as disaster recovery | They live in the same account and die with the server; a lockout or a mis-scoped delete takes both | Off-provider or append-only copy, and a restore that has actually been timed (`storage.md`) |
| Reusing one API token across environments | No scoping exists inside a project, and none exists across them either | One project and one token per environment (Rule 2) |
| Building a fleet on auction hardware | Each auction machine is a different spec that will not be available again | Auction for one-offs; the product line when the spec must be reproducible (`dedicated.md`) |
| Running mail without checking port 25 and rDNS | New accounts cannot send at all, and the ranges carry reputation history | Unblock, set rDNS, verify SPF/DKIM/DMARC — or relay and skip the problem (`mail.md`) |
| Expecting AWS-style IAM | There is no role, no policy, no condition key inside a project | Design isolation with projects and tokens instead of permissions |
| Reading the invoice as the resource list | The invoice shows what bills, including things nobody remembers creating | Reconcile invoice against a live resource listing every month (`costs.md`) |
| Sizing from a diagram | Diagrams omit MTU, traffic allowances, the missing default route, and per-account caps | Walk Limits That Force Designs against the diagram before building |

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The instruction 'Read this file only when WRITING' does not clearly define what counts as 'writing' or the exact trigger conditions for activating this skill content. In a markdown skill file, such broad wording can overlap with many ordinary editing situations and may cause unintended invocation because it lacks explicit scope or exclusion conditions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The document instructs readers to tear down the source and delete orphans after cutover, which can permanently remove infrastructure or data. While rollback timing is discussed, there is no explicit warning that these deletions are irreversible or that operators should confirm backups and recovery before proceeding.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The exit procedure instructs deletion of servers, projects, and inventory records, but does not explicitly warn that these actions may be irreversible or require backup/retention validation before execution. In an operational skill, this can lead to premature deletion of infrastructure or records, reducing recovery options and potentially causing data loss or billing/accountability issues.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
memory-template.md:60