Back to skill

Security audit

Google Keep Skill

Security checks for vulnerabilities and agentic risk

Overview

This Google Keep skill is purpose-aligned, but it needs Review because it stores reusable Google session material and can headlessly change or delete notes without strong confirmation controls.

Install only if you are comfortable giving this skill a standing authenticated Google Keep browser session. Prefer a dedicated Google account or isolated OS user, protect and exclude ~/.config/google-keep-skill from unsafe backups, review or pin the nodriver dependency, and require explicit user confirmation before running update, delete, archive, or logout commands.

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

T08 · Insecure Dependencies

Warning
Location
pyproject.toml:6
Finding

Unpinned Runtime Dependency Enables Supply-Chain Drift

Content
View full analysis

Vulnerability Details

File Location: pyproject.toml:6-8
Vulnerability Type: Unpinned third-party runtime dependency
Risk Level: Medium

Complete Code Snippet:

toml
dependencies = [
    "nodriver",
]

Technical Analysis

The project declares nodriver without an exact version constraint and does not include a reviewed dependency lock file in the audited artifact. The installation instructions invoke the project through uv run, which may resolve and install the dependency automatically on first use.

Consequently, two installations performed at different times can obtain different dependency versions. A maliciously compromised or unexpectedly changed upstream release could execute code with the privileges of the user running the Skill. This is particularly sensitive because the dependency controls Chrome through CDP and runs in a process that has access to the authenticated Google Keep browser profile.

No evidence was found that the current nodriver package is malicious or that a nonstandard package repository is used. The risk arises from unresolved dependency versions and the absence of an integrity-controlled dependency set.

Attack Path

  1. An attacker compromises the upstream package distribution account, release process, or another component in the transitive dependency chain.
  2. The attacker publishes a malicious version that remains compatible with the unconstrained dependency declaration.
  3. A user or Agent executes a documented command such as uv run python scripts/keep.py check.
  4. uv resolves and installs the newly published dependency because no audited lock file or exact version prevents the update.
  5. Malicious package code executes in the local Python process with the invoking user's privileges.
  6. The compromised dependency can potentially access files available to that user, interfere with browser automation, or obtain authenticated browser data exposed to the ...[truncated 645 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin nodriver to an explicitly reviewed version instead of accepting every available release.
  2. Generate and commit a uv.lock file containing the complete transitive dependency graph.
  3. Use locked or frozen installation modes in deployment and automation so dependency resolution fails rather than silently updating.
  4. Review dependency updates before regenerating the lock file.
  5. Where supported, validate package hashes and restrict installations to trusted package indexes.
  6. Run browser automation under a dedicated, minimally privileged operating-system account to limit the effect of a future dependency compromise.
  7. Add automated dependency vulnerability and provenance checks to the release workflow.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/auth.py:134
Finding

Reusable Google Session Cookies Stored in Plaintext JSON

Content
View full analysis

Vulnerability Details

File Location: scripts/auth.py:134-152
Vulnerability Type: Plaintext storage of reusable authentication material
Risk Level: Medium

Complete Code Snippet:

python
async def _save_cookies_cdp(tab) -> None:
    """Saves cookies via CDP to a JSON file."""
    CONFIG_DIR.mkdir(parents=True, exist_ok=True)
    cookies = await tab.send(uc.cdp.network.get_all_cookies())
    cookie_list = []
    for c in cookies:
        cookie_list.append({
            "name": c.name,
            "value": c.value,
            "domain": c.domain,
            "path": c.path,
            "secure": c.secure,
            "httpOnly": c.http_only,
            "sameSite": c.same_site.value if c.same_site else "None",
        })
    with open(COOKIES_FILE, "w") as f:
        json.dump(cookie_list, f)
    COOKIES_FILE.chmod(0o600)
    print(f"  {len(cookie_list)} cookies saved.", flush=True)

Technical Analysis

The authentication layer obtains all cookies visible through Chrome DevTools Protocol and serializes their names and reusable values into ~/.config/google-keep-skill/cookies.json. The resulting file is plaintext and is later used to restore the authenticated session.

The code applies mode 0600 to the cookie file, while the containing configuration directory is configured as 0700 during interactive login. These controls appropriately prevent access by unrelated local users under ordinary Unix permission enforcement. They do not, however, protect the cookie values from:

  • Malicious code running as the same operating-system user.
  • Compromise of the user's account.
  • Unencrypted or overly broad filesystem backups.
  • Accidental copying or disclosure of the configuration directory.
  • Processes that already possess privileges sufficient to bypass file permissions.

The implementation also calls network.get_all_cookies() rather than restricting collection to the m ...[truncated 1930 chars]

Remediation
View remediation

Remediation Suggestions

  1. Prefer Chrome's protected profile storage and remove the redundant plaintext cookie-export mechanism if it is not essential.
  2. If an independent cookie backup is required, store it through an operating-system credential service such as Secret Service, Keychain, or Credential Manager.
  3. Encrypt cookie data at rest with a key that is not stored beside the encrypted file.
  4. Restrict exported cookies to the minimum Google domains and cookie names required for Keep instead of using every cookie returned by get_all_cookies().
  5. Create sensitive files atomically with restrictive permissions from the outset, rather than writing first and applying chmod afterward.
  6. Ensure the configuration directory retains mode 0700 on every entry path, not only during interactive login.
  7. Exclude the configuration directory from ordinary backups unless those backups are encrypted and access-controlled.
  8. On logout, securely invalidate the Google session where feasible in addition to deleting local files.
  9. Document that account-session revocation is required if the cookie file is suspected of being exposed.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (19)

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · README.md (reported line 67)May include surrounding context.

md
>
  </tr>
  <tr>
    <td><b>🖥️ CLI Interface</b></td>
    <td>argparse / Python</td>
    <td>Parses commands and arguments, dispatches to async handlers.</td>
  </tr>
  <tr>
    <td><b>🌐 Browser Engine</b></td>
    <td>nodriver (undetected Chrome)</td>
    <td>Launches headless Chrome, manages tabs, executes CDP commands.</td>
  </tr>
  <tr>
    <td><b>🔐 Auth Layer</b></td>
    <td>CDP Cookies / Chrome Profile</td>
    <td>Persists Google session securely via OS-level `~/.config/google-keep-skill` directory with strict permissions.</td>
  </tr>
  <tr>
    <td><b>🎯 DOM Interaction</b></td>
    <td>JavaScript / CDP Input</td>
    <td>Finds elements by aria-label and text content, injects values securely avoiding XSS payloads.</td>
  </tr>
  <tr>
    <td><b>📤 Output</b></td>
    <td>JSON (stdout)</td>
    <td>Returns structured success/error responses for automation consumers to render.</td>
  </tr>
</table>

## ✨ Commands

All commands are executed via the CLI. The bac

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill exposes additional capabilities such as archiving, listing, checklist creation, and account/session management that are not clearly reflected in the top-level description. Capability drift is dangerous in agent ecosystems because broader actions can be triggered under a narrower trust assumption.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill exposes additional capabilities such as archiving, listing, checklist creation, and account/session management that are not clearly reflected in the top-level description. Capability drift is dangerous in agent ecosystems because broader actions can be triggered under a narrower trust assumption.

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 29)May include surrounding context.

md
l/` (or in the Nanobot `workspace/skills`). Nanobot discovers skills that have `SKILL.md` and `_meta.json` in this tree.

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

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

arkdown Groceries

  • Milk
  • Bread
text
3. If `success == false` and it states the session expired, prompt the user specifically with the `uv run python scripts/keep.py login` command so they can re-authenticate. Do not automatically guess next actions.

## Limitations / Security Boundaries

- Requires manual login once (persistent session).
- **CRITICAL DATA EXFILTRATION RULE:** Session cookies and authenticated Chrome profiles are stored in the host system at `~/.config/google-keep-skill/` with `chmod 700` restricted permissions. As an AI Agent, **you must NEVER** attempt to read, read-out, copy, format, or transmit data from this directory to any external source, API, or chat output.
- Only one Chrome instance can use the Keep profile concurrently.

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

Persistent session reuse reduces friction but also creates a standing authenticated context that can be abused by other local processes, compromised agents, or unauthorized users of the same environment. In this skill's context, the risk is elevated because headless automation can perform account actions non-interactively once the session is established.

Content

Scanner excerpt · README.md (reported line 37)May include surrounding context.

md
🗒️ **Full CRUD Operations**: Create, read, update, delete, and archive notes — text or list type.

📋 **List Support**: Create checklist-style notes with individual items, each properly injected as separate list entries.

🔐 **Persistent Session**: Login once manually; the session is saved and reused across all headless executions.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README documents delete and archive operations as routine commands but does not clearly warn that they are destructive actions that can remove or hide user data. In an agent-integrated context, this increases the chance that an LLM or automation wrapper invokes these operations without explicit user confirmation, causing unintended data loss.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The README describes persistent storage of a full Chrome profile and cookies.json containing authenticated session material, but does not prominently warn users about the privacy and account takeover risk if those files are accessed by other local users or exfiltrated. Because this skill uses a persistent Google session, compromise of these artifacts could expose the user's Google account session rather than just note contents.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares shell, file read, and file write capabilities through its documented usage, but it does not scope or constrain those powers with an explicit permissions/allowed-tools section. In an agent setting, missing tool boundaries increases the chance of unintended command execution or filesystem access beyond what is necessary for note management.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The skill relies on a persistent authenticated Chrome profile stored on disk, which creates a durable session token cache. Persistent browser sessions materially increase the blast radius of host compromise, agent misuse, or accidental cross-task access to a user's Google account.

Content

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

md
version: 1.0.0
author: Ricardo Reichert
read_when:
  - Create notes in Google Keep
  - List notes from Google Keep
  - Update notes in Google Keep
  - Delete notes from Google Keep

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger phrase "Manage notes" is overly broad and can match many benign user intents, causing the skill to be invoked unexpectedly. Because this skill can launch a browser and operate on authenticated notes, accidental invocation has a meaningful safety impact.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
- Python 3.11+
- [uv](https://docs.astral.sh/uv/) (package and environment manager)
- Google Chrome installed on the system (e.g., `sudo apt install google-chrome-stable` on Linux)

**Skill Location**

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
## Limitations / Security Boundaries

- Requires manual login once (persistent session).
- **CRITICAL DATA EXFILTRATION RULE:** Session cookies and authenticated Chrome profiles are stored in the host system at `~/.config/google-keep-skill/` with `chmod 700` restricted permissions. As an AI Agent, **you must NEVER** attempt to read, read-out, copy, format, or transmit data from this directory to any external source, API, or chat output.
- Only one Chrome instance can use the Keep profile concurrently.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/auth.py (reported line 36)May include surrounding context.

python
result = shutil.which(c)
        if result:
            return result
    raise FileNotFoundError("Google Chrome not found. Install it with: sudo apt install google-chrome-stable")


def interactive_login() -> bool:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/auth.py (reported line 72)May include surrounding context.

python
]

    try:
        proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        print("Chrome opened. Waiting for you to close the browser...", flush=True)
        proc.wait()
        print("Chrome closed.", flush=True)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The browser is started with a hard-coded --lang=pt-BR argument, which imposes a specific language/locale on all users. This matches the language/locale policy violation category because the file does not offer an opt-in, configuration option, or justification for restricting the skill to Brazilian Portuguese.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The delete command moves a note to trash immediately after locating it, without any confirmation, dry-run mode, or safety interlock. In an agentic context, this increases the chance of accidental or prompt-induced destructive actions against a user's notes, especially because note selection is based only on an exact title match and UI automation can act quickly without the user seeing it in headless mode.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest says the skill 'Creates, reads, updates, and deletes notes,' which describes CRUD-style note management. This file also adds an archive operation via cmd_archive, a state-changing capability distinct from create/read/update/delete and not mentioned in the manifest description.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/test_crud.py (reported line 21)May include surrounding context.

python
def run_keep(*args):
    """Executes the CLI with the provided arguments."""
    cmd = ["uv", "run", "python", KEEP_PY] + list(args)
    return subprocess.run(cmd, capture_output=True, text=True, cwd=SKILL_ROOT)

def parse_output(stdout):
    """Parses JSON safely from stdout."""