Back to skill

Security audit

kipris-cli

Security checks for vulnerabilities and agentic risk

Overview

The skill is a purpose-aligned KIPRIS search CLI, but it sends the user's API key over plain HTTP by default, so it should be reviewed before installation.

Review before installing. Use only if you can change or verify the endpoint is HTTPS, avoid passing the key with --key where it may appear in process listings, do not set KIPRIS_BASE to untrusted hosts, and run the cron example only with a private state directory.

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

T09 · Insecure Skill Coding Practices

Error
Location
bin/_kipris_common.sh:5
Finding

KIPRIS API Key Transmitted Through Plaintext HTTP and Exposed in the Process Command Line

Content
View full analysis
&2; exit 1; } require_key() { local k="${KIPRIS_PLUS_KEY:-${KIPRIS_KEY:-}}" if [ -n "${OVERRIDE_KEY:-}" ]; then k="$OVERRIDE_KEY"; fi if [ -z "$k" ]; then die "missing API key. Set KIPRIS_PLUS_KEY or pass --key. Get one at https://plus.kipris.or.kr" fi printf '%s' "$k" } # urlencode a single string. Pure Python (no extra deps). urlencode() { python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1], safe=''))" "${1:-}" } # Call a KIPRIS Plus REST endpoint. # args: # Emits raw XML to stdout, exits 0 on HTTP success regardless of resultCode. kipris_get() { local path="$1" qs="${2:-}" local key; key="$(require_key)" local sep="?" [ -n "$qs" ] && sep="?${qs}&" local url="${KIPRIS_BASE}/${path}${sep}ServiceKey=${key}" curl -sS --fail-with-body -m 30 -A "kipris-cli/0.1.0" "$url" } ``` ### Technical Analysis The default KIPRIS endpoint uses `http://`, so TLS does not protect the API key, search parameters, or server response. The code appends the credential to the URL as `ServiceKey=${key}` and passes the complete URL to `curl` as a command-line argument. This creates several exposure channels: 1. A network observer can read or modify the plaintext HTTP request. 2. A local process observer may obtain the complete URL, including the key, from process inspection facilities while `curl` is running. 3. HTTP proxies, debugging systems, shell tracing, and URL-oriented request logs may record the credential. 4. Because `KIPRIS_BASE` is accepted from the environment without scheme or host validation, a manipulated execution environment can direct the key ...[truncated 1659 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
examples/competitor-patent-watch.sh:17
Finding

Predictable Cron Cursor File Allows Symlink-Based File Corruption

Content
View full analysis
> "$CURSOR_FILE" ``` ### Technical Analysis The example is explicitly described as suitable for cron, but its state file is a predictable relative pathname. It calls `touch` and later opens the same path with an append redirection without checking whether the path is a symbolic link, whether its parent directory is trusted, or whether the file is owned by the expected account. Both `touch` and the shell append redirection follow symbolic links. If the cron job runs from a directory writable by another local user, that user can create the predicted cursor path as a symbolic link to another file writable by the cron account. The default file also inherits permissions from the invoking account's umask. A permissive umask can make the cursor readable or writable by unintended local users. The optional third argument permits an arbitrary cursor location but receives no path or ownership validation. ### Attack Path 1. A cron job is configured to run the example from a shared or attacker-writable working directory ...[truncated 1277 chars]
Remediation
View remediation
&2 exit 1 } ``` This check should be combined with a trusted private directory because a standalone check can still be subject to a time-of-check/time-of-use race. 3. Create new files atomically with restrictive permissions. Use `mktemp` inside the private state directory, write the updated state to that file, set mode `0600`, and atomically rename it into place. 4. Verify that any existing cursor is a regular file owned by the effective user and is not group- or world-writable. 5. Resolve and validate a user-supplied cursor path before use, or remove support for arbitrary paths in the cron-oriented example. 6. Use file locking when concurrent runs are possible so two scheduled instances cannot race while reading and updating the cursor. 7. Document that the script must not run from a shared writable directory and recommend an explicit, protected working directory in the cron configuration. ]]>
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)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill documentation describes a CLI that performs outbound API requests and is invoked via shell commands, but the manifest does not declare any explicit tool scope such as allowed network access or shell permissions. This creates an authorization gap: agents or platforms may execute a capability-bearing skill without clear least-privilege constraints, increasing the chance of unintended command execution or unrestricted external requests.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.