T09 · Insecure Skill Coding Practices
- Location
SKILL.md:135- Finding
Ambiguous Tombstone Matching Can Purge Unrelated VM State
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 135–147
Vulnerability Type: Ambiguous resource identification and unsafe destructive operation
Risk Level: MediumVulnerable Code
bash # discover tombstone python3 - <<'PY' import glob, os vm='<name>' paths=glob.glob('/opt/hermes-vmctl/state/deleted/*.json') c=[p for p in paths if vm in os.path.basename(p)] if c: c.sort(key=os.path.getmtime, reverse=True) print(os.path.basename(c[0])[:-5]) PY vmctl purge <deleted_name>Technical Analysis
The tombstone-discovery procedure identifies candidate files by checking whether the original VM name appears anywhere in the tombstone filename:
python vm in os.path.basename(p)This is a substring comparison rather than an exact comparison against a canonical VM identifier. If several tombstones contain the same name fragment, the procedure silently selects the most recently modified candidate. It does not parse the JSON record, validate ownership, compare an exact VM name or identifier, or require a unique match before recommending a permanent purge.
For example, a VM named
vmctl-test-smoke-123could match tombstones associated with bothvmctl-test-smoke-123andvmctl-test-smoke-123-copy. Selecting by modification time does not establish that the selected tombstone belongs to the VM deleted during the current smoke test.The eventual
vmctl purgeoperation is destructive, so using an ambiguously selected identifier creates a resource-confusion vulnerability.Attack Path
- A tombstone for another VM exists under
/opt/hermes-vmctl/state/deleted. - Its filename contains the smoke-test VM name as a substring, or the smoke-test name contains an overlapping resource-name fragment.
- The unrelated tombstone has a later modification time than the intended tombstone.
- The documented Python procedure returns the unrelated tombstone ...[truncated 863 chars]
- A tombstone for another VM exists under
- Remediation
View remediation
Remediation Suggestions
- Parse each tombstone JSON file and compare its canonical VM name or immutable VM identifier exactly.
- Require exactly one matching tombstone. Stop without purging if zero or multiple matches are found.
- Correlate the tombstone with the VM created and deleted during the current execution, preferably through an immutable identifier returned by
vmctl. - Validate that the selected resource name begins with the required
vmctl-test-prefix before purging. - Display the selected tombstone and require operator confirmation when identity cannot be established unambiguously.
- Pass the resulting name as a properly quoted argument rather than relying on manual placeholder substitution.
A hardened implementation should follow this pattern:
python import glob import json import os import sys expected_name = os.environ["VM_NAME"] matches = [] for path in glob.glob("/opt/hermes-vmctl/state/deleted/*.json"): with open(path, encoding="utf-8") as handle: record = json.load(handle) if record.get("name") == expected_name: matches.append(path) if len(matches) != 1: raise SystemExit( f"Expected exactly one tombstone for {expected_name!r}; " f"found {len(matches)}" ) print(os.path.basename(matches[0])[:-5])The actual JSON field should be adjusted to the documented
vmctltombstone schema.
