Back to skill

Security audit

Karakeep

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its Karakeep bookmark purpose, but its API key handling and network safeguards need user review before installation.

Review this before installing if your Karakeep bookmarks or token are sensitive. Prefer using an HTTPS instance URL, avoid relying on the hardcoded default URL, restrict permissions on `~/.config/karakeep/config.json`, and consider pinning or preinstalling dependencies in a controlled environment.

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

Warning
Location
scripts/karakeep-cli.py:27
Finding
API Key Stored in a Plaintext Configuration File Without Explicit Permission Hardening## Vulnerability Details **File Location**: `scripts/karakeep-cli.py`, lines 27-31 **Vulnerability Type**: Plaintext sensitive credential storage **Risk Level**: Medium ### Vulnerable Code ```python def save_config(url, api_key): config_path = os.path.expanduser("~/.config/karakeep/config.json") os.makedirs(os.path.dirname(config_path), exist_ok=True) with open(config_path, 'w') as f: json.dump({"url": url, "api_key": api_key}, f) ``` ### Technical Analysis The `login` command persists the Karakeep API key directly in a plaintext JSON file. Neither the configuration directory nor the file is created with an explicit owner-only permission mode. Consequently, their effective permissions depend on the invoking process's `umask` and any preexisting directory or file permissions. The code also writes directly to the destination file rather than creating a restricted temporary file and atomically replacing the configuration. Although no race-condition exploit is confirmed from the available code alone, direct writes make robust permission and integrity handling more difficult. ### Attack Path 1. A user invokes the documented `login` command with a valid Karakeep API key. 2. `save_config()` writes that key to `~/.config/karakeep/config.json` as plaintext. 3. On a system with a permissive `umask`, inherited ACL, or preexisting broadly readable configuration file, another local account or process reads the file. 4. The attacker extracts the `api_key` and associated instance URL. 5. The attacker uses the stolen bearer credential against the Karakeep API. ### Impact Assessment Exploitation requires local read access to the configuration file, such as access through another local account, a compromised process, an overly broad ACL, or a backup process that exposes the file. It does not directly grant operating-system privilege escalation. A stolen API key may allow the attacker to exercise all Karak ...[truncated 340 chars]
Remediation
## Remediation Suggestions - Create `~/.config/karakeep` with owner-only permissions, such as mode `0700`. - Create the configuration file with mode `0600` using an API that applies the restrictive mode at file creation time. - Verify and repair permissions on an existing configuration file before writing credentials. - Write through a securely created temporary file in the same directory, flush it, apply mode `0600`, and atomically replace the destination. - Prefer an operating-system credential manager or keyring rather than storing the API key in JSON. - Document that environment variables can also be exposed to other processes or diagnostic tooling and should not be treated as a complete secret-management solution. - Consider supporting short-lived, narrowly scoped API tokens to reduce the impact of credential disclosure.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/karakeep-cli.py:44
Finding
Bearer Credentials Can Be Transmitted Over Unencrypted HTTP## Vulnerability Details **File Location**: `scripts/karakeep-cli.py`, lines 44-47 **Related Input Location**: `scripts/karakeep-cli.py`, lines 103-104 **Vulnerability Type**: Missing HTTPS enforcement for authenticated requests **Risk Level**: High ### Vulnerable Code ```python full_url = f"{url.rstrip('/')}{endpoint}" try: response = requests.request(method, full_url, headers=headers, json=data, params=params) ``` The server URL is accepted without scheme validation: ```python login_parser = subparsers.add_parser("login") login_parser.add_argument("--url", help="Karakeep instance URL") login_parser.add_argument("api_key") ``` The credential attached to the request is constructed immediately before the vulnerable request: ```python headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } ``` ### Technical Analysis The CLI accepts an arbitrary instance URL and concatenates it with API endpoints without requiring an `https://` scheme. Every API request includes the Karakeep API key as an HTTP bearer token. If a user configures an `http://` URL, requests sends the authorization header and bookmark data without transport encryption. An attacker with the ability to observe or modify network traffic can recover the bearer token because bearer credentials do not provide protection against interception or replay. The issue applies to listing, searching, and adding bookmarks because all operations use the shared `make_request()` function. ### Attack Path 1. A user runs `login --url http://example-karakeep.local API_KEY`, or an existing configuration supplies an HTTP URL. 2. The CLI stores or loads the HTTP URL and API key. 3. The user invokes `list`, `list --search`, or `add`. 4. `make_request()` constructs an HTTP URL and sends `Authorization: Bearer API_KEY`. 5. An attacker on the same wireless network, local network segment, proxy path, or anot ...[truncated 883 chars]
Remediation
## Remediation Suggestions - Parse the configured URL with a standard URL parser and require the scheme to be `https`. - Reject URLs with missing schemes, embedded credentials, malformed hosts, or unexpected URL components. - If plaintext HTTP is necessary for local development, require an explicit option such as `--allow-insecure-http` and restrict it to loopback addresses by default. - Display a prominent warning before any insecure request and never silently downgrade from HTTPS. - Retain TLS certificate verification; do not introduce a general-purpose option that disables verification. - Consider restricting redirects or validating redirect destinations before forwarding the authorization header. - Remove ambiguous URL defaults and require the user to explicitly configure the intended trusted Karakeep instance.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:14
Finding
Unpinned Third-Party Dependency Is Resolved During Normal Skill Execution## Vulnerability Details **File Location**: `SKILL.md`, lines 14-33 **Vulnerability Type**: Unpinned runtime dependency and supply-chain exposure **Risk Level**: Medium ### Vulnerable Instructions ```bash uv run --with requests skills/karakeep/scripts/karakeep-cli.py login --url <instance_url> <api_key> ``` ```bash uv run --with requests skills/karakeep/scripts/karakeep-cli.py add <url> ``` ```bash uv run --with requests skills/karakeep/scripts/karakeep-cli.py list --limit 10 ``` ```bash uv run --with requests skills/karakeep/scripts/karakeep-cli.py list --search "title:react is:fav" ``` ### Technical Analysis The documented commands use `uv run --with requests` without a pinned version or a reviewed lockfile. This causes dependency resolution to occur as part of normal command execution and allows the selected package version to change after the Skill has been reviewed. The risk depends on the package indexes and resolver configuration used in the execution environment. If an index is compromised, replaced, or configured to prefer an untrusted source, a malicious or unauthorized package artifact can be installed and imported by the Python process. An incompatible future package release can also unexpectedly change runtime behavior even in the absence of a malicious package. This is a supply-chain weakness rather than evidence that the legitimate `requests` package is malicious. ### Attack Path 1. The user or agent follows a documented command containing `uv run --with requests`. 2. `uv` resolves the unpinned dependency using the environment's configured package indexes and cache. 3. An attacker compromises a configured index, controls an added index or mirror, poisons package resolution, or otherwise causes an unauthorized artifact to be selected. 4. The dependency is installed into the runtime environment. 5. `karakeep-cli.py` executes `import requests`. 6. Code in the selected ...[truncated 888 chars]
Remediation
## Remediation Suggestions - Pin `requests` and all transitive dependencies to reviewed versions. - Maintain and distribute a committed lockfile generated from a trusted package source. - Use hash verification so package artifacts must match expected cryptographic hashes. - Configure `uv` to use an explicitly trusted package index and avoid unreviewed supplemental indexes. - Resolve and install dependencies during a controlled build or deployment phase rather than during each normal Skill invocation. - Periodically update pinned versions through a documented review and vulnerability-management process. - Consider executing the Skill in a constrained environment with limited filesystem access, network access, and credential exposure to reduce the impact of a dependency compromise.
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (1)

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill invokes a Python script that uses network access and reads/writes configuration and secrets, but the manifest does not declare any tool scope such as permissions or allowed-tools. This creates a trust and containment gap: an agent or reviewer cannot easily tell that running the skill may access environment variables, write config files, and make outbound requests to a Karakeep instance.

Static analysis

No suspicious patterns detected.