T09 · Insecure Skill Coding Practices
- Location
scripts/ledger.py:166- Finding
Existing ledger history can be erased without an enforced confirmation gate
- Content
View full analysis
Vulnerability Details
File Location:
scripts/ledger.py, lines 166–184 and 507
Vulnerability Type: Destructive state replacement without executable confirmation enforcement
Risk Level: Mediumpython def cmd_init(args): data_dir = args.data_dir path = group_path(data_dir, args.group) if os.path.exists(path) and not args.force: die(f"group '{args.group}' already exists at {path} (use --force to reset)") members = [m.strip() for m in args.members.split(",") if m.strip()] if args.members else [] state = { "group": args.group, "currency": args.currency.upper(), "members": members, "expenses": [], "next_id": 1, "created_at": now_iso(), } save_group(data_dir, args.group, state) print(f"Created group '{args.group}' ({state['currency']}) with members: " f"{', '.join(members) if members else '(none yet -- add with add-member)'}") print(f"Ledger file: {group_path(data_dir, args.group)}")python s.add_argument("--force", action="store_true", help="overwrite an existing group")Technical Analysis
When the target group file already exists,
cmd_initprevents replacement only if--forceis absent. Supplying the Boolean flag bypasses the check immediately. The function then constructs a fresh state with an emptyexpensesarray and passes it tosave_group, which atomically replaces the existing ledger file.SKILL.mdinstructs the Agent to useinit --forceonly when the user explicitly requests a reset and after confirmation. However, this safeguard exists only as natural-language guidance. The executable entry point does not require a confirmation token, interactive approval, target-name repetition, backup, or other technical evidence of authorization.Consequently, an Agent or another caller that invokes the script directly can cross the documented authorization bounda ...[truncated 1430 chars]
- Remediation
View remediation
Remediation Suggestions
- Require a non-Boolean confirmation value tied to the exact target, such as
--confirm-reset-group "Goa Trip", and reject the operation unless it exactly matches--group. - For interactive use, display the existing ledger path and expense count and require an explicit confirmation before replacement.
- For non-interactive Agent use, require the target-bound confirmation argument so natural-language guidance cannot be bypassed by direct invocation.
- Create a timestamped backup of the existing ledger before resetting it, using restrictive file permissions and an atomic write.
- Consider separating destructive reset behavior from
initinto a dedicatedresetcommand to reduce accidental invocation. - Add regression tests proving that an existing ledger cannot be replaced using only
--forceand that an invalid or mismatched confirmation value is rejected.
- Require a non-Boolean confirmation value tied to the exact target, such as
