Back to skill

Security audit

Target Shopping

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed Target shopping helper, but its guest-cart link creates a temporary cart token that should be treated as sensitive.

Install only if you are comfortable with the skill contacting Target's public web endpoints and creating anonymous guest carts. Treat generated cart URLs and cart HTML files like temporary private links, avoid pasting the full access_token URL into chat or logs, use --no-open when you do not want a browser launched, and delete generated cart files after use.

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

Warning
Location
scripts/cart_link.py:58
Finding
Guest cart bearer token exposed through unsafe temporary files and standard output<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/_auth.py:37-44` - `scripts/_auth.py:105-125` - `scripts/cart_link.py:58-60` - `scripts/cart_link.py:65-97` - `scripts/cart_link.py:204-218` - `scripts/cart_link.py:277` **Vulnerability Type**: Sensitive token exposure through unsafe temporary-file handling and logging **Risk Level**: Medium ### Vulnerable Code Token cache path creation: ```python def _cache_path() -> Path: base = os.environ.get("TARGET_TOKEN_CACHE_DIR") if base: d = Path(base) else: d = Path(tempfile.gettempdir()) / "target-com-shopper" d.mkdir(parents=True, exist_ok=True) return d / "anonymous-token.json" ``` The token is written before restrictive permissions are applied: ```python def get_token(*, force_refresh: bool = False) -> dict[str, Any]: """Return a cached token if still valid, otherwise mint and cache a new one. The cache is a plain JSON file under TARGET_TOKEN_CACHE_DIR (or a temp dir). """ path = _cache_path() if not force_refresh and path.exists(): try: cached = json.loads(path.read_text()) exp = cached.get("_payload", {}).get("exp", 0) if exp - time.time() > EXPIRY_SKEW_S: return cached except (ValueError, KeyError, OSError): pass fresh = mint_token() try: path.write_text(json.dumps(fresh)) # Tighten perms — token grants cart write access. os.chmod(path, 0o600) except OSError: pass return fresh ``` The redirect file is created in a predictable temporary directory without explicit restrictive permissions: ```python def _default_cart_file(cart_id: str | None) -> Path: base = Path(tempfile.gettempdir()) / "target-com-shopper" base.mkdir(parents=True, exist_ok=True) suffix = cart_id or f"unknown-{int(time.time())}" return base / f"cart-{suffix}.html" ``` The redirect file contains the complete bearer URL: ```pyth ...[truncated 5946 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Create a private cache directory** - Create the directory with mode `0700`. - Verify that it is a real directory, is owned by the current user, and is not a symbolic link. - Prefer a per-user runtime directory such as `$XDG_RUNTIME_DIR` when available. 2. **Create sensitive files securely** - Use exclusive creation with `os.open()` flags such as `O_CREAT | O_EXCL | O_WRONLY`. - Set mode `0600` at creation time rather than applying `chmod()` after writing. - Reject symbolic links with platform-appropriate safeguards such as `O_NOFOLLOW`. - Write to a securely created temporary file and use an atomic rename where replacement is required. 3. **Protect redirect files** - Create bearer-token HTML files with mode `0600`. - Avoid predictable fallback names based only on timestamps. - Use cryptographically random filenames. - Delete the redirect file after successful browser handoff or after a short expiration period. 4. **Remove the full token from default output** - Do not include the complete `url` field in normal command output. - Return only `cart_file`, `auto_opened`, `url_preview`, and non-sensitive shopping-list information by default. - If programmatic access to the URL is required, place it behind an explicit opt-in option such as `--include-sensitive-url`. - Clearly mark opt-in output as sensitive and unsuitable for logs or chat transcripts. 5. **Minimize token lifetime and reuse** - Request the shortest token lifetime supported by the upstream service. - Avoid reusing tokens longer than necessary. - Remove expired cache files promptly. 6. **Add security regression tests** - Assert that the cache directory is mode `0700`. - Assert that cache and redirect files are mode `0600`. - Assert that default stdout does not contain `access_token=`. - Test behavior when paths are pre-existing symbolic links or owned by another user. - Test that sensitive temp ...[truncated 69 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (18)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The supplied code is narrowly focused on product detail page retrieval by TCIN. It accepts a TCIN, store identifiers, and visitor ID, calls a product-details API, and formats the response. While store_id/pricing_store_id influence pricing context, the code does not implement the broader declared functionality: there is no search flow, no stock/availability or pickup ETA logic, and no cart-link generation. This is a material description-behavior mismatch because the declared purpose describes a multi-capability shopping assistant, while this chunk only performs PDP lookup.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The supplied code chunk is narrowly focused on reviews: it calls a Target API operation named product_review_v1 with a TCIN and channel=WEB, then extracts ratings_and_reviews statistics such as review count, average rating, distribution, and secondary attributes. This is materially different from the declared description, which describes product search, store stock lookup, pickup ETA checks, and guest-cart deep-link creation. Review retrieval is an undeclared capability, and the primary purpose of this code chunk does not match the declared behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The code chunk shown is not the user-facing skill logic; it is a pytest live smoke test module for public Target endpoints. It validates search, PDP, summary, fulfillment, store lookup, and reviews APIs. Most tested behaviors align partially with the declared browsing/stock-checking purpose, but the chunk also covers reviews, which are not mentioned in the description. More importantly, a key declared capability—building a guest-cart deep link—is not represented anywhere in this code chunk. Because the actual code provided primarily functions as a test harness and includes an undeclared reviews capability while omitting a declared core capability, the description does not accurately represent this specific supplied code chunk.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill advertises and documents capabilities that require network, shell execution, local file writes, and environment access, but it does not declare any explicit tool scope or permission boundaries in the manifest. That increases the risk of over-broad execution in an agent runtime because the assistant may invoke sensitive capabilities without a least-privilege contract or user-visible gating.

Session Persistence

Medium
Category
Rogue Agent
Content
**The cart-link feature creates a real server-side guest cart.** It mints
a 24-hour anonymous bearer token against `gsp.target.com` and POSTs TCINs
to `carts.target.com`. Treat the resulting URL like a one-time share link:
it grants ~24h of cart-write access to whoever holds it. No login, payment
info, or shipping address is ever transmitted.

**No checkout, payment, or auth.** Checkout, returns, saved carts, Circle
Confidence
91% confidence
Finding
The skill creates and caches a 24-hour bearer token that grants cart-write access and embeds that token in a deep link and local HTML file. Even though it is 'only' a guest cart, disclosure through chat logs, temp files, browser history, or other local users would let anyone possessing the token modify the cart during its lifetime.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The documentation instructs consumers to pass a live bearer token in the browser URL query string (`/cart?access_token=...`). Tokens in URLs are routinely exposed through browser history, bookmarks, screenshots, copied links, logs, analytics, crash reports, and the `Referer` header to downstream resources, allowing unintended parties to replay the guest cart session during the token lifetime. In this skill’s context, the token is unauthenticated and guest-scoped, which limits account takeover risk, but it still grants control over the anonymous cart and normalizes an unsafe token transport pattern.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The code writes a local HTML file containing a live 24-hour cart bearer token in the URL query string, creating a local artifact with sensitive capability that can be reopened, copied, or discovered by other local processes or users. This also exceeds the manifest's stated behavior by persisting a tokenized handoff file on disk, which increases the attack surface even if the feature is meant as a convenience.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
Automatically launching the user's default browser is a side effect on the local system that is not clearly disclosed by the skill description and can trigger unintended navigation with a live bearer-token URL. In agent settings, undisclosed local actions are risky because they reduce user control and can cause unexpected data exposure or execution of a privileged desktop capability.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
Auto-opening a browser is not strictly required to build a guest-cart link, so it introduces an unnecessary local capability beyond core functionality. Because the opened destination includes a temporary cart-write token, any automatic navigation increases the chance of token leakage via browser history, crash reports, shared desktop sessions, or user confusion about what was launched.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The argparse description says the tool provides 'Review summary + top reviews for a TCIN,' but the implementation and inline comments make clear that the endpoint only returns summary stats and that full review text is not exposed here. This is an active contradiction in the file's own documentation, not just an omission.

Unverifiable Dependency: pytest has 2 known advisory(ies) (CVE-2025-71176 (pytest has vulnerable tmpdir handling); CVE-2025-71176 (pytest has vulnerable tmpdir handling)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Missing User Warnings

Low
Confidence
83% confidence
Finding
This code sends request parameters to an external API via c.api_get, including visitor_id and store identifiers assembled in params. While the module docstring describes search functionality, it does not warn that identifier data is transmitted, and there is no visible prompt or user-facing notice in this file about that network transmission.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
This JSON fixture contains a natural-language locale value, "America/Chicago", that fixes the location locale to a specific region. Under the policy, forcing a specific locale without user opt-in or a documented region-specific justification is a natural-language policy violation.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
This JSON fixture contains a natural-language locale value, "America/Chicago", that fixes the location locale to a specific region. Under the policy, forcing a specific locale without user opt-in or a documented region-specific justification is a natural-language policy violation.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
This JSON fixture contains a natural-language locale value, "America/Chicago", that fixes the location locale to a specific region. Under the policy, forcing a specific locale without user opt-in or a documented region-specific justification is a natural-language policy violation.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
This JSON fixture contains a natural-language locale value, "America/Chicago", that fixes the location locale to a specific region. Under the policy, forcing a specific locale without user opt-in or a documented region-specific justification is a natural-language policy violation.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
This JSON fixture contains a natural-language locale value, "America/Chicago", that fixes the location locale to a specific region. Under the policy, forcing a specific locale without user opt-in or a documented region-specific justification is a natural-language policy violation.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The natural-language product description hardcodes compatibility and marketing content in English only, with no indication of user language choice or a justified region-specific constraint. Because SQP-3 applies to all file types, this qualifies as a locale-policy concern in the file's natural-language content.

Static analysis

No suspicious patterns detected.