Back to skill

Security audit

Card Benefits Tracker

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent local credit-card benefits tracker, but its tracking command can be tricked into reading or replacing JSON files outside its own data folder.

Review this skill before installing. It stores and updates a local financial profile of card ownership, benefits, usage, dates, and selected reward preferences. The main issue to fix is strict validation of tracking periods so values like ../cards cannot read or modify JSON outside data/. Also verify any web-searched benefit or cashback information before saving it.

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 (1)

T09 · Insecure Skill Coding Practices

Error
Location
api/cli.py:70
Finding
Path Traversal in Tracking File Operations## Vulnerability Details **File Location**: `api/cli.py:70-98`, with affected command handlers at `api/cli.py:352-366`, `api/cli.py:388-409`, and `api/cli.py:430-481` **Vulnerability Type**: Path traversal leading to unauthorized JSON file read and modification **Risk Level**: High ### Vulnerable Code ```python def tracking_path(period): """Return absolute path for a tracking file given period like 2026_02.""" return os.path.join(DATA_DIR, f"{period}.json") def read_tracking(period): """Read a tracking file, return None if it doesn't exist.""" path = tracking_path(period) if not os.path.exists(path): return None with open(path, "r", encoding="utf-8") as f: return json.load(f) def write_tracking(period, data): """Atomically write a tracking file.""" os.makedirs(DATA_DIR, exist_ok=True) path = tracking_path(period) fd, tmp_path = tempfile.mkstemp(dir=DATA_DIR, suffix=".tmp") try: with os.fdopen(fd, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) f.write("\n") os.replace(tmp_path, path) except Exception: if os.path.exists(tmp_path): os.unlink(tmp_path) raise ``` Representative affected handlers read the supplied period before validating it: ```python def cmd_tracking_get(args): existing = read_tracking(args.period) if existing is not None: output(True, data=existing) # Auto-generate data = generate_tracking_data(args.period) write_tracking(args.period, data) output(True, data=data) def cmd_tracking_use(args): existing = read_tracking(args.period) if existing is None: # Auto-generate first existing = generate_tracking_data(args.period) write_tracking(args.period, existing) ``` Additional affected handlers follow the same pattern: ```p ...[truncated 5091 chars]
Remediation
## Remediation Suggestions 1. Validate `args.period` before every read or write: ```python def require_valid_period(period): if parse_period(period) is None: output(False, error=f"Invalid period format: {period}. Use YYYY_MM.") return period ``` 2. Apply validation at the beginning of every tracking handler, including `get`, `use`, `unuse`, `generate`, `add-entry`, and `remove-entry`. 3. Enforce path confinement after canonicalization: ```python from pathlib import Path DATA_ROOT = Path(DATA_DIR).resolve() def tracking_path(period): if parse_period(period) is None: raise ValueError("Period must use YYYY_MM format") candidate = (DATA_ROOT / f"{period}.json").resolve() if candidate.parent != DATA_ROOT: raise ValueError("Tracking path escapes the data directory") return str(candidate) ``` 4. Reject path separators, traversal components, absolute paths, and any period not matching exactly four digits, an underscore, and a valid two-digit month. 5. Keep validation inside `tracking_path()` as a defense-in-depth measure so future command handlers cannot accidentally bypass it. 6. Add regression tests for all tracking actions using inputs such as `../target`, `../../target`, absolute paths, invalid months, encoded separators where relevant, and valid values such as `2026_02`. 7. Run the CLI with least-privilege filesystem permissions so the process cannot read or replace unrelated application files.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The code is clearly related to credit card benefits, so the domain matches, but the implemented functionality is much narrower than the declared description. It only loads card data from a local JSON file and produces a monthly/quarterly summary report of available benefits and aggregate values. It does not manage cards, record benefit usage, issue reminders, compute ROI, or optimize spending categories. It also does not analyze yearly benefits. This is a material description-behavior mismatch because the declared purpose presents a substantially more capable tracking and optimization tool than the supplied code actually implements.

Self-Modification

High
Category
Rogue Agent
Content
tr_gen = tr_sub.add_parser("generate", help="Generate/regenerate tracking file")
    tr_gen.add_argument("period", help="Period in YYYY_MM format")
    tr_gen.add_argument("--force", action="store_true", help="Overwrite existing file")

    tr_add = tr_sub.add_parser("add-entry", help="Add a custom benefit entry")
    tr_add.add_argument("period", help="Period in YYYY_MM format")
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill instructs the agent to read and write local files via a Python CLI, but it does not declare any explicit tool scope or allowed-tools boundary. That mismatch weakens least-privilege controls and can cause the runtime to grant broader file capabilities than users or reviewers would expect.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The skill expands from local benefit tracking into external web retrieval by directing the agent to search with ddgs for card benefits. This introduces unnecessary network access, risks pulling untrusted or inaccurate data into the workflow, and can expose user intent or card interests to third-party services.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The spending optimization section introduces Chinese trigger phrases, Chinese headings, and Chinese example output, but the skill does not state that language selection is based on user preference or provide an explicit opt-in choice. This can violate language/locale policy because the skill may default to a specific language for some interactions without user selection.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The category-optimization workflow depends on ddgs searches for current cashback rates, adding live network retrieval beyond a local tracking skill's core purpose. That broadens the attack surface and may lead to unreliable recommendations based on manipulated, stale, or malicious search results.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
This JSON file contains multiple natural-language fields such as benefit names and notes in Chinese, while card names and other fields remain in English. Because the file provides no opt-in, alternate locale, or justification that the skill is intended only for Chinese-speaking users, it can violate language/locale policy expectations.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The file’s title, docstrings, and generated report content are written in Chinese, and the script constructs its output entirely in Chinese without any opt-in or alternate locale path. This can violate a language/locale policy when skills are expected to respect user preference unless a region-specific constraint is explicitly documented.

Natural-Language Policy Violations

Low
Confidence
83% confidence
Finding
This file contains user-facing benefit names in multiple languages, including Chinese-only labels and mixed Chinese/English strings. Because the content does not document that language choice is intentional or user-selected, it may violate a policy requiring language or locale opt-in rather than forcing a specific presentation.

Natural-Language Policy Violations

Low
Confidence
86% confidence
Finding
This JSON contains user-facing text in Chinese for some benefit_name values, while other entries are in English. Because the file mixes locales without any indication of user choice or documented region-specific justification, it may violate the language/locale policy for natural-language content.

Natural-Language Policy Violations

Low
Confidence
86% confidence
Finding
This JSON contains user-facing text in Chinese for some benefit_name values, while other entries are in English. Because the file mixes locales without any indication of user choice or documented region-specific justification, it may violate the language/locale policy for natural-language content.

Natural-Language Policy Violations

Low
Confidence
86% confidence
Finding
This JSON contains user-facing text in Chinese for some benefit_name values, while other entries are in English. Because the file mixes locales without any indication of user choice or documented region-specific justification, it may violate the language/locale policy for natural-language content.

Natural-Language Policy Violations

Low
Confidence
86% confidence
Finding
This JSON contains user-facing text in Chinese for some benefit_name values, while other entries are in English. Because the file mixes locales without any indication of user choice or documented region-specific justification, it may violate the language/locale policy for natural-language content.

Natural-Language Policy Violations

Low
Confidence
86% confidence
Finding
This JSON contains user-facing text in Chinese for some benefit_name values, while other entries are in English. Because the file mixes locales without any indication of user choice or documented region-specific justification, it may violate the language/locale policy for natural-language content.

Natural-Language Policy Violations

Low
Confidence
86% confidence
Finding
This JSON contains user-facing text in Chinese for some benefit_name values, while other entries are in English. Because the file mixes locales without any indication of user choice or documented region-specific justification, it may violate the language/locale policy for natural-language content.

Static analysis

No suspicious patterns detected.