Back to skill

Security audit

OurGroceries Integration

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches OurGroceries list management, but it needs Review because it handles real account credentials and logs an authenticated session cookie.

Only install after reviewing the credential risks. This skill can read and modify a real OurGroceries account using your email and password. The session-cookie debug log should be removed or redacted before use, credentials should come from a secure environment or vault rather than a plaintext env file, and destructive actions such as item/list deletion should require explicit confirmation. Avoid using the DevTools monitor on a real account unless you understand that it prints private request data to the browser console.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
lib/ourgroceries/__init__.py:129
Finding

Authentication Session Cookie Exposed Through Debug Logging

Content
View full analysis

Vulnerability Details

File Location: lib/ourgroceries/__init__.py, lines 129–133
Vulnerability Type: Sensitive session-token exposure through application logs
Risk Level: High

Vulnerable Code

python
cookies = session.cookie_jar.filter_cookies(BASE_URL)
for key, cookie in cookies.items():
    if key == COOKIE_KEY_SESSION:
        self._session_key = cookie.value
        _LOGGER.debug('ourgroceries found _session_key {}'.format(self._session_key))

Technical Analysis

After authentication, the client copies the complete ourgroceries-auth session-cookie value into a debug log message. Session cookies are bearer credentials: possession of a valid value may be sufficient to issue authenticated requests without knowing the account password.

Although the message uses the debug level, debug logging is commonly enabled during troubleshooting and may be captured by terminal logs, support bundles, CI systems, service managers, or centralized logging platforms. Logging the complete value unnecessarily expands the number of systems and users that can access the authenticated session.

Attack Path

  1. Debug logging is enabled for the ourgroceries logger.
  2. A user runs any operation that invokes OurGroceries.login().
  3. The client authenticates and receives the ourgroceries-auth session cookie.
  4. The complete cookie value is written to a local or centralized log.
  5. An attacker with access to those logs extracts the cookie.
  6. The attacker supplies the cookie in requests to OurGroceries.
  7. If the session remains valid and the service does not enforce additional binding controls, the attacker performs operations as the affected account.

Impact Assessment

Successful exploitation may provide access equivalent to the authenticated OurGroceries session. This can expose shopping-list names, items, notes, and identifiers and may allow modification or deletion of lists and items sup ...[truncated 243 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove the session value from all log messages.

  • Replace the vulnerable statement with a constant message:

    python
    _LOGGER.debug("ourgroceries session established")
    
  • Add a logging policy that explicitly prohibits passwords, cookies, authorization headers, and API tokens.

  • Review retained debug logs and support bundles for previously exposed values.

  • Invalidate active sessions if affected logs may have been accessible to unauthorized parties.

  • Add an automated test that captures log output during login and verifies that the session value is absent.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/load_skill_env.py:8
Finding

Automatic Loading of Plaintext Credentials Without File-Security Validation

Content
View full analysis

Vulnerability Details

File Location: scripts/load_skill_env.py, lines 8–25
Vulnerability Type: Insecure local secret storage and unrestricted environment-variable import
Risk Level: Medium

Vulnerable Code

python
def apply() -> None:
    path = Path(__file__).resolve().parent.parent / "env"
    if not path.is_file():
        return
    for raw in path.read_text(encoding="utf-8").splitlines():
        line = raw.strip()
        if not line or line.startswith("#"):
            continue
        if "=" not in line:
            continue
        key, _, val = line.partition("=")
        key = key.strip()
        val = val.strip()
        if not key:
            continue
        if len(val) >= 2 and val[0] == val[-1] and val[0] in "'\"":
            val = val[1:-1]
        os.environ.setdefault(key, val)

Technical Analysis

Every executable Python script calls this loader before reading account credentials. The loader automatically reads a plaintext file at the fixed project-root path env, but it does not verify the file owner, permissions, or whether the path is safe from untrusted modification.

It also accepts any nonempty key rather than restricting imports to OURGROCERIES_EMAIL and OURGROCERIES_PASSWORD. Existing environment values are protected by setdefault, which reduces overwrite risk, but missing variables can still be populated from a locally controlled file.

Project documentation states that the credential file is gitignored. However, the audited directory structure contains no .gitignore, so that protection is not present in the supplied artifact. This creates a risk of credentials being exposed through permissive filesystem access, backups, artifact packaging, or accidental source-control inclusion.

Attack Path

Credential-disclosure path:

  1. A user stores their email address and password in the project-root env file as documented.
  2. The f ...[truncated 1455 chars]
Remediation
View remediation

Remediation Suggestions

  • Prefer runtime secret injection from the host environment or a dedicated secret manager.

  • Do not automatically load plaintext credentials in production or agent-managed execution.

  • If local file support is retained, allow only the expected variables:

    python
    ALLOWED_KEYS = {
        "OURGROCERIES_EMAIL",
        "OURGROCERIES_PASSWORD",
    }
    
    if key not in ALLOWED_KEYS:
        continue
    
  • On platforms that support it, reject files not owned by the current user or accessible by group and other users.

  • Require restrictive permissions such as mode 0600.

  • Add an actual .gitignore containing at least:

    gitignore
    env
    .env
    .env.local
    
  • Add secret-scanning checks to source-control and release pipelines.

  • Document that credential files must never be included in archives, logs, support bundles, or repository commits.

  • Encourage users to rotate credentials if an env file has previously been committed or distributed.

T08 · Insecure Dependencies

Warning
Location
references/api_reference.md:37
Finding

Contradictory Documentation Directs Users to Install an Unnecessary Unpinned Package

Content
View full analysis

Vulnerability Details

File Location: references/api_reference.md, lines 37–41
Vulnerability Type: Unnecessary third-party dependency installation and supply-chain exposure
Risk Level: Medium

Vulnerable Code

markdown
## Installation
The package is already installed:
```bash
pip install ourgroceries
text

### Technical Analysis

The API reference instructs users or automation agents to install the `ourgroceries` package from the default Python package index without a version constraint or integrity hash. This package is unnecessary for the supplied scripts because they explicitly prepend the project’s vendored `lib/` directory and import the bundled implementation.

The instruction also contradicts `AGENTS.md` and `RELEASE_NOTES.md`, both of which state that the PyPI package must not be installed. An agent relying on the API reference may therefore execute package installation code that is outside the audited artifact and whose contents may change over time.

This is an insecure dependency workflow rather than evidence that the named package is currently malicious. The risk arises from unnecessary execution of an unpinned external package and inconsistent authoritative documentation.

### Attack Path

1. A user or automation agent reads `references/api_reference.md`.
2. It follows the documented command `pip install ourgroceries`.
3. The package installer resolves the current package and its transitive dependencies from the configured package index.
4. Package installation or build logic executes with the privileges of the user running `pip`.
5. A compromised, substituted, or unexpectedly changed package release can execute code or introduce vulnerable components.
6. The installed package may also cause behavioral confusion because it differs from the vendored implementation the scripts are designed to use.

### Impact Assessment

The maximum impact depends on the privileges used to invok
...[truncated 548 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove the pip install ourgroceries command from the API reference.

  • State clearly that the Skill uses the vendored client under lib/ourgroceries/.

  • Make all documentation consistently direct users to install only the declared requirements:

    bash
    python3 -m venv .venv
    . .venv/bin/activate
    python3 -m pip install -r requirements.txt
    
  • Pin aiohttp and its dependency set to versions tested by the project.

  • Use a lockfile or hash-validated requirements file for reproducible installations.

  • Run dependency vulnerability and provenance checks as part of release preparation.

  • Designate one authoritative installation document and automatically test documentation commands to prevent future contradictions.

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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented purpose is grocery-list management, but the skill also references a DevTools network monitor that intercepts and logs POST/XHR/fetch payloads from the live web app. That behavior is materially different from the declared function and can expose authentication tokens, account data, or request contents gathered from a user's browser session.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documented purpose is grocery-list management, but the skill also references a DevTools network monitor that intercepts and logs POST/XHR/fetch payloads from the live web app. That behavior is materially different from the declared function and can expose authentication tokens, account data, or request contents gathered from a user's browser session.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 16)May include surrounding context.

md
2. Install **`aiohttp`** (see `requirements.txt`). Scripts load a **vendored client** from `lib/ourgroceries/` (patched for current OurGroceries APIs, including

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code logs the authenticated session cookie value at debug level, exposing a bearer credential that can be replayed to act as the user. In environments where debug logs are aggregated, shared, or retained, this can lead to account takeover of the user's grocery account and unauthorized reads/modifications/deletions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The file documents use of account credentials and scripts that perform live HTTP operations against a real OurGroceries account, including adding and removing list items, without any explicit warning about privacy sensitivity or the fact that actions modify user data. In an agent setting, this can lead to unintended account access or state-changing actions being performed without adequate user awareness or confirmation.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
79% confidence
Finding

The skill declares capabilities that involve environment-variable access, file reads, and network interaction, but it does not define an explicit tool/permission scope. That makes the operational boundary unclear to users and reviewers, increasing the chance that sensitive credentials or network actions occur without sufficient transparency or policy enforcement.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The trigger phrases are broad enough to overlap with ordinary shopping-related conversation, which can cause accidental invocation of a credentialed skill. In this context, accidental activation is more dangerous because the skill can perform account actions such as adding, removing, or modifying grocery-list data over the network.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill advertises destructive actions like deleting lists and account-backed synchronization using stored credentials, but it does not prominently warn users about data transmission or the consequences of those actions. Without explicit notice and confirmation, users may unknowingly send account data to a third-party service or trigger irreversible modifications.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code constructs a login form with the user's email address and password, then immediately submits it over HTTP(S) to the remote service. Although there are debug logs, there is no user-facing confirmation, warning comment, or disclosure in this file that credentials will be transmitted to a third-party service.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The manifest describes a skill for managing shopping lists on OurGroceries.com: adding items, checking lists, and synchronizing lists. However, this module also exposes account-level metadata operations such as reading category lists, creating categories, accessing the master list, adding items to the master list, and changing item/category values, which goes beyond straightforward shopping-list management as described.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

delete_list is documented as Create a new shopping list and logs create_list even though it deletes a list; change_item_on_list is documented/logged like an add operation even though it edits an existing item; and nearby methods such as get_category_list/get_master_list also have swapped debug labels. These comments and log messages actively misstate the intent of the operations, which can mislead reviewers and downstream users about destructive or mutating behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This script is explicitly designed to hook XMLHttpRequest and fetch in the browser and log full POST bodies for OurGroceries /your-lists requests, including an easy-to-copy EXPORT line. Even though presented as a devtools helper, it captures authenticated application traffic and can expose list contents, identifiers, categories, and other account-linked request data to anyone with console access or to copied/shared logs, which exceeds normal grocery-list management behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script performs an irreversible state-changing action against a real OurGroceries account immediately after resolving the item and list, without any confirmation, dry-run mode, or safeguard. In an agent/voice-command context, ambiguous input, transcription mistakes, or prompt-driven misuse could cause unintended deletion of grocery items from a user's synced lists.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This markdown file says it is for automation agents 'implementing or debugging list changes' but does not define when the skill should be invoked versus when it should not. Without explicit trigger phrases, scope boundaries, or negative examples, the activation conditions are broad and potentially overlap with many ordinary list-management requests.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The constructor defaults the locale to 'en-US', and later requests send that locale to the service. This imposes a specific language/locale behavior by default without offering an explicit user choice or documenting why that locale is required.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency is specified as aiohttp>=3.9.0, which allows installation of any later version and makes builds non-reproducible. This can lead to accidental adoption of vulnerable or breaking releases over time, especially for a network-facing HTTP library with a history of security advisories.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
aiohttp>=3.9.0

Unverifiable Dependency: aiohttp has 16 known advisory(ies) (CVE-2024-52303 (aiohttp has a memory leak when middleware is enabled when requesting a resource ); CVE-2026-54279 (aiohttp: Host-Only Cookies Become Domain Cookies After CookieJar Persistence); CVE-2026-34514 (AIOHTTP has CRLF injection through multipart part content type header constructi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
93% confidence
Finding

Because aiohttp is not pinned, there is no way to verify from this manifest whether the installed version avoids known security advisories affecting some aiohttp releases. Given that this skill interacts with a remote web service using an HTTP client library, dependency ambiguity increases the chance of deploying a version exposed to request-handling, cookie, or header-related vulnerabilities.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.