T09 · Insecure Skill Coding Practices
- Location
scripts/client.py:17- Finding
OAuth Credentials and Tokens Are Stored in an Unprotected Plaintext State File
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This Kroger/QFC shopping skill is mostly purpose-aligned, but it handles sensitive OAuth credentials in a local plaintext state file and can create live pickup orders without a documented confirmation step.
Review this skill before installing if you intend to connect a real Kroger account. Use it only in a trusted private workspace, keep state.json out of sync folders and source control, revoke Kroger credentials if that file is exposed, and require the agent to show the cart contents, store, pickup time, and final action before any cart clear or pickup order creation.
scripts/client.py:17OAuth Credentials and Tokens Are Stored in an Unprotected Plaintext State File
scripts/client.py:137OAuth Authorization Flow Omits CSRF State Validation
The skill documents destructive and irreversible actions such as cart clearing and pickup order creation, but it does not instruct the agent to obtain explicit user confirmation or warn about side effects before execution. In an agent setting, this increases the risk of unintended purchases, order placement, or loss of cart contents from ambiguous prompts or automation errors.
The client persists OAuth access tokens, refresh tokens, and client secrets into a local JSON state file without any protection, minimization, or warning to the user. In this skill context, those credentials can be reused to impersonate the user against the Kroger API if the file is read by another local user, malware, backups, or accidentally committed to source control.
The order creation path directly issues a live external purchase action once invoked, with no confirmation prompt, dry-run mode, or secondary validation of order contents. In an agent or CLI workflow, malformed input, automation mistakes, or prompt-driven misuse could place unintended grocery orders on the user's account.
The argument help text and default value hard-code chain ID 213 as QFC, and the same default appears in other commands. This creates a built-in regional or business preference without asking the user to choose, which can conflict with language/locale-style policy expectations for user choice.
The locations command silently defaults to chain ID 213, which appears to correspond to a specific regional brand. Repeating this default across commands strengthens the implicit preference without an explicit user selection step.
The grocery subcommand defaults to chain ID 213, again embedding a specific retailer preference into the workflow. This is a natural-language/configuration choice presented to users without clear opt-in or justification.
No suspicious patterns detected.