Vehicle Expense Tracker
ReviewAudited by ClawScan on May 10, 2026.
Overview
The skill mostly matches its vehicle-expense purpose, but its file and spreadsheet writes are not safely scoped and its dry-run can still change local config.
Review before installing. If you use it, restrict the Google credential to only the intended spreadsheet, avoid vehicle/category names containing slashes or '..', do not trust dry-run as fully no-write until fixed, and prefer a patched version that constrains photo paths and escapes spreadsheet formulas.
Findings (5)
Artifact-based informational review of SKILL.md, metadata, install specs, static scan signals, and capability signals. ClawScan does not execute the skill or run runtime probes.
A mistaken or malicious vehicle/category value could make the skill create directories and copy files outside the intended vehicle expense folder.
The destination directory for photo copies is built directly from vehicle_name and category without sanitizing or resolving those path components. Absolute paths or '..' components could escape PHOTO_BASE_DIR.
target_dir = Path(PHOTO_BASE_DIR) / vehicle_name / category ... target_dir.mkdir(parents=True, exist_ok=True) ... shutil.copy2(src, dst)
Sanitize vehicle and category path components, reject absolute paths and '..', resolve the final path, and enforce that it remains under the configured photo base directory.
If untrusted receipt text or a crafted description starts with spreadsheet formula characters, it could become an active formula in the user's Google Sheet.
User-provided category, cost, unit, and description values are sent to Google Sheets as USER_ENTERED data, which can cause formula-like values to be interpreted by the spreadsheet.
row_data = [
args.mileage,
category,
final_cost,
quantity,
unit,
args.description,
args.date
] ... valueInputOption='USER_ENTERED'Use RAW for text insertion or escape leading formula characters such as '=', '+', '-', and '@' before writing user-controlled text to spreadsheets.
A user may believe dry-run makes no changes, but the skill can still edit its local config file.
The config save can occur before the dry-run branch, so a preview run can still mutate persistent config for new categories or save flags.
if args.save_unit or args.save_default or (category not in category_defaults): ... save_config(config) ... if args.dry_run:
Move all persistent writes after the dry-run check, or clearly document and separately confirm config updates during dry-run.
The skill can add expense rows to any configured spreadsheet that the Google credential can access.
The skill uses Google Sheets API credentials from another auth helper to append rows. This is expected for the stated Google Sheets integration, but it is a real delegated account permission.
from google_auth import get_service
sheets = get_service('sheets', 'v4') ... spreadsheets().values().append(Use a dedicated Google service account with access only to the intended vehicle-expense spreadsheet.
Google Sheets mode depends on code outside this skill package, so behavior also depends on the installed google-workspace skill.
The skill imports runtime code from a sibling google-workspace skill that is not included in this manifest. This is understandable for shared Google auth, but it expands the trusted code base.
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../google-workspace')))
Install google-workspace only from a trusted source and declare this dependency clearly in the skill metadata or setup instructions.
