Back to skill

Security audit

Discogs Cli

Security checks for vulnerabilities and agentic risk

Overview

This Discogs skill appears purpose-aligned, but it handles a reusable account token in ways users should review before installing.

Review this before installing if you use a real Discogs account token. Prefer a narrowly scoped token, avoid entering it in commands that may be logged, check permissions on ~/.config/discogs-cli/config.yaml, and be aware that wantlist commands modify your Discogs account while sync/art commands create local cache files.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/cmd/config.go:23
Finding
Discogs Personal Access Token Exposed Through Command-Line Arguments## Vulnerability Details **File Location**: `SKILL.md:27-31`, `README.md:46-51`, `scripts/cmd/config.go:23-27`, and `scripts/cmd/config.go:46` **Vulnerability Type**: Sensitive credential exposure through process arguments **Risk Level**: Medium **Vulnerable code and documented usage:** ```go token, _ := cmd.Flags().GetString("token") username, _ := cmd.Flags().GetString("username") if token != "" { viper.Set("token", token) fmt.Println("Set 'token' in config.") } ``` ```go setCmd.Flags().StringP("token", "t", "", "Discogs Personal Access Token") setCmd.Flags().StringP("username", "u", "", "Discogs Username") ``` ```bash skills/discogs-cli/bin/discogs-cli config set -u "YourUsername" -t "YourSecretToken" ``` ### Technical Analysis The documented configuration procedure requires the personal access token to be supplied as the value of the `-t` command-line option. Command-line arguments are not an appropriate secret-input channel because they can be retained in shell history, Agent execution transcripts, command telemetry, audit logs, and diagnostic output. On some operating systems, other local users may also be able to inspect process arguments while the command is running. Although the token is legitimately required to authenticate to Discogs, exposing it through process arguments is not necessary for the Skill’s declared functionality. ### Attack Path 1. A user or Agent follows the documented setup command and places the Discogs token after `-t`. 2. The complete command is retained in shell history, an Agent tool-call record, process monitoring data, or another command log. 3. An attacker or unauthorized local user obtains access to that retained data. 4. The attacker extracts the token and submits authenticated requests to Discogs. 5. The attacker can exercise any Discogs account capabilities granted to that token, including reading private account data or modifying the wantlist where aut ...[truncated 402 chars]
Remediation
## Remediation Suggestions - Remove the token command-line flag as the recommended secret-input mechanism. - Read the token from a masked interactive prompt using a terminal password-input API. - For noninteractive Agent operation, accept the token through standard input or a narrowly scoped environment variable, while ensuring it is not logged. - Prefer storing the token in an operating-system credential manager or secret service. - Remove literal token placeholders from executable command examples and clearly warn users not to place secrets in command history. - Review and redact existing Agent transcripts, shell histories, and automation logs that may contain tokens. - Advise affected users to revoke and rotate any token previously supplied through logged command lines.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/cmd/root.go:50
Finding
Plaintext Credential Storage Does Not Enforce Owner-Only Permissions## Vulnerability Details **File Location**: `scripts/cmd/root.go:50-58` and `scripts/cmd/config.go:26-35` **Vulnerability Type**: Insecure plaintext secret storage and permissive filesystem permissions **Risk Level**: Medium **Vulnerable code:** ```go // Search config in home directory with name ".config/discogs-cli" (without extension). configPath := home + "/.config/discogs-cli" viper.AddConfigPath(configPath) viper.SetConfigName("config") viper.SetConfigType("yaml") // Create the config file if it doesn't exist os.MkdirAll(configPath, os.ModePerm) viper.SafeWriteConfig() ``` ```go if token != "" { viper.Set("token", token) fmt.Println("Set 'token' in config.") } if username != "" { viper.Set("username", username) fmt.Println("Set 'username' in config.") } if err := viper.WriteConfig(); err != nil { log.Fatalf("Error writing config file: %s", err) } ``` ### Technical Analysis The application stores the Discogs token as plaintext YAML under `~/.config/discogs-cli/config.yaml`. It creates the containing directory using `os.ModePerm`, which requests mode `0777` before application of the process umask. The code does not explicitly enforce mode `0700` on the directory or `0600` on the credential file, and it does not validate or repair permissions on an existing path. Consequently, actual confidentiality depends on the invoking environment’s umask and any pre-existing filesystem state. This does not support the README’s claim that credentials are stored securely. The return values from `os.MkdirAll` and `viper.SafeWriteConfig` are also ignored, reducing the reliability of security-sensitive initialization. ### Attack Path 1. The Skill initializes its configuration under an environment with a permissive umask, or an attacker prepares an existing configuration path with weak permissions. 2. The user saves a Discogs personal access token through `config set`. 3. Viper write ...[truncated 773 chars]
Remediation
## Remediation Suggestions - Create the configuration directory with mode `0700` rather than `os.ModePerm`. - Create and maintain the configuration file with mode `0600`. - Check and handle every error from directory creation and configuration-file creation. - Before reading or writing credentials, inspect existing file ownership, type, and permissions; reject symlinks and files not owned by the current user. - Correct overly permissive permissions on existing installations. - Prefer an operating-system keychain or credential service instead of plaintext YAML. - If plaintext fallback is unavoidable, store only non-secret configuration in YAML and clearly document the residual risk. - Update the README’s “stored securely” claim unless secure storage is implemented.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/cmd/art.go:92
Finding
Album-Art Cache Uses a Hard-Coded Workspace Path and Permissive Directory Mode## Vulnerability Details **File Location**: `scripts/cmd/art.go:92-105` **Vulnerability Type**: Unsafe predictable file creation in an overly permissive fixed directory **Risk Level**: Low **Vulnerable code:** ```go // Define the cache directory path within the OpenClaw workspace cacheDir := "/home/Ev05bot/.openclaw/workspace/art_cache/discogs" // Create the directory including any necessary parents if err := os.MkdirAll(cacheDir, os.ModePerm); err != nil { fmt.Println("Error creating cache directory:", err) return } // Save the image to the cache fileName := fmt.Sprintf("%d.jpg", releaseID) filePath := filepath.Join(cacheDir, fileName) file, err := os.Create(filePath) ``` ### Technical Analysis The cache is tied to the fixed account path `/home/Ev05bot/.openclaw/workspace/` rather than the invoking user’s cache directory. The directory is requested with `os.ModePerm` (`0777` before umask), and image files use predictable release-ID names. `os.Create` follows symbolic links and truncates an existing target. If an attacker can write to the cache directory, the attacker may create a symbolic link named after a release ID and cause a later art download to overwrite a file writable by the victim. The hard-coded path can also place files in an unintended user or workspace context. ### Attack Path 1. The effective directory permissions or existing filesystem configuration allow an attacker to write in the album-art cache. 2. The attacker predicts a release ID that the victim will request. 3. The attacker creates `<release_id>.jpg` as a symbolic link to a file that the victim account can modify. 4. The victim runs `discogs-cli release art <release_id>`. 5. `os.Create` follows the symbolic link, truncates the target, and writes downloaded image bytes to it. This path requires attacker write access to the cache directory and a target writable by the victim process. ### Impact Assessment The pot ...[truncated 338 chars]
Remediation
## Remediation Suggestions - Obtain the cache root through `os.UserCacheDir()` and append an application-specific directory. - Create private cache directories with mode `0700`, or use `0750` only where deliberate group sharing is required. - Create cache files with mode `0600`. - Refuse to follow symbolic links by using platform-appropriate no-follow file creation or by safely validating the path and file type. - Write to a newly created temporary file in the same directory and atomically rename it into place. - Validate existing directory ownership and permissions before writing. - Avoid hard-coded usernames and workspace paths. - Apply response-size limits before copying remote image data to disk to reduce disk-exhaustion risk.

T08 · Insecure Dependencies

Note
Location
install.sh:20
Finding
Go Build Lacks Project-Local Dependency Version and Integrity Locking## Vulnerability Details **File Location**: `install.sh:20-23`; project root lacks `go.mod` and `go.sum` **Vulnerability Type**: Unpinned and non-reproducible third-party dependency resolution **Risk Level**: Low **Vulnerable build code:** ```bash # 2. Navigate to the source directory echo "==> Changing directory to $SCRIPTS_DIR" cd "$SCRIPTS_DIR" # 3. Build the Go binary echo "==> Building Go binary..." go build -o "$BINARY_PATH" . ``` The source imports third-party modules, including: ```go "github.com/irlndts/go-discogs" "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/mitchellh/go-homedir" "github.com/schollz/progressbar/v3" ``` ### Technical Analysis The supplied project has no `go.mod` or `go.sum`, despite relying on multiple third-party packages. The installer runs `go build` without establishing a project-local dependency graph or checksum set. Depending on the Go environment, the build may fail or may resolve dependencies through ambient GOPATH state, a parent module, local replacements, or other environment-specific configuration. As a result, the binary is not reproducibly tied to the code and dependency versions reviewed during this audit. No malicious dependency was identified in the supplied files. The risk is that unreviewed or attacker-influenced dependency state can become part of the resulting binary. ### Attack Path 1. The build runs in an environment containing an unexpected parent module, local replacement directive, GOPATH package, or otherwise attacker-controlled dependency state. 2. `go build` resolves one or more imported packages from that ambient state. 3. The compiler incorporates code that is not represented or integrity-locked in the audited project. 4. The user executes the resulting binary with access to the Discogs token, local configuration, cache directories, and network. 5. A malicious substituted dependency can act with the same operating-system ...[truncated 600 chars]
Remediation
## Remediation Suggestions - Add a project-root `go.mod` declaring the module path, Go version, and explicit dependency versions. - Generate and commit `go.sum` to enable checksum verification. - Run builds from the directory containing the project’s own `go.mod`. - Use `go mod verify` in the installation or release pipeline. - Review and intentionally update dependencies through controlled pull requests. - Run vulnerability and license scanning against the locked module graph. - Build release artifacts in a clean environment without inherited parent modules, workspace files, or untrusted replacement directives. - Consider setting a controlled `GOWORK` policy during release builds to prevent unintended workspace-module substitution.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (22)

Credential Access

High
Category
Privilege Escalation
Content
*   **Fetch Album Art:** Download and display the cover art for any release.
*   **Search Database:** Search for artists, releases, and labels on Discogs.
*   **Manage Wantlist:** List, add, or remove items from your wantlist.
*   **Secure Configuration:** Your Discogs username and personal access token are stored securely in a local configuration file.

## Getting Started
Confidence
89% confidence
Finding
The feature list advertises storage of a personal access token in a local configuration file, which involves handling reusable credentials. In an agent-skill context, credentials are especially sensitive because they may grant account actions such as wantlist modification and collection access, and poor storage guidance can normalize unsafe secret handling.

Chaining Abuse

High
Category
Tool Misuse
Content
You must have the Go programming language toolchain installed.

*   **Debian/Ubuntu:** `sudo apt-get update && sudo apt-get install -y golang-go`
*   For other systems, follow the official installation instructions at [go.dev](https://go.dev/doc/install).

### Installation & Configuration
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Credential Access

High
Category
Privilege Escalation
Content
This will create a `discogs-cli` executable inside the `./scripts/` directory.

3.  **Set Your Credentials:**
    Run the `config set` command to securely save your Discogs username and a Personal Access Token.
    ```bash
    ./scripts/discogs-cli config set -u "YourDiscogsUsername" -t "YourDiscogsToken"
    ```
Confidence
91% confidence
Finding
The README explicitly instructs users to pass a personal access token on the command line. Command-line secrets can be exposed through shell history, process listings, logging, terminal scrollback, or agent/tool telemetry, making this a real credential-handling weakness.

Tp4

High
Category
MCP Tool Poisoning
Confidence
87% confidence
Finding
The declared description emphasizes managing a user's vinyl record collection on Discogs, which implies collection-oriented operations such as viewing, adding, removing, or organizing owned records. The provided code instead defines a command namespace for interacting with a specific Discogs release and indicates functionality for release details or album art. This is a materially different primary purpose from personal collection management, so the description does not accurately represent the supplied code chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding
The code is focused narrowly on Discogs wantlist operations, not broader vinyl record collection management. It performs GET/PUT/DELETE requests against the Discogs /users/{username}/wants endpoints to list, add, and remove wanted releases. While this is related to Discogs and vinyl records, the declared description suggests collection management generally, which is materially different from a specific wantlist feature. No unrelated capabilities or suspicious behaviors are present.

Chaining Abuse

High
Category
Tool Misuse
Content
This skill is a Go program and requires the Go toolchain to be installed.

**Installation (Debian/Ubuntu):**
`sudo apt-get update && sudo apt-get install -y golang-go`

## One-Time Setup
Confidence
79% confidence
Finding
The chained command combines update and install under sudo in a single copy-pasteable line, reducing opportunities for review and making privileged execution more automatic. In security-sensitive contexts, command chaining can mask failures, unexpected behavior, or future modifications if the line is copied blindly.

Credential Access

High
Category
Privilege Escalation
Content
rootCmd.AddCommand(configCmd)
	configCmd.AddCommand(setCmd)

	setCmd.Flags().StringP("token", "t", "", "Discogs Personal Access Token")
	setCmd.Flags().StringP("username", "u", "", "Discogs Username")
}
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
rootCmd.AddCommand(configCmd)
	configCmd.AddCommand(setCmd)

	setCmd.Flags().StringP("token", "t", "", "Discogs Personal Access Token")
	setCmd.Flags().StringP("username", "u", "", "Discogs Username")
}
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
You must have the Go programming language toolchain installed.

*   **Debian/Ubuntu:** `sudo apt-get update && sudo apt-get install -y golang-go`
*   For other systems, follow the official installation instructions at [go.dev](https://go.dev/doc/install).

### Installation & Configuration
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
-   **Option A: Move the binary (Recommended)**
        Move the compiled `discogs-cli` binary to a standard location like `/usr/local/bin`.
        ```bash
        sudo mv ./scripts/discogs-cli /usr/local/bin/discogs-cli
        ```

    -   **Option B: Create a Symbolic Link**
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
-   **Option A: Move the binary (Recommended)**
        Move the compiled `discogs-cli` binary to a standard location like `/usr/local/bin`.
        ```bash
        sudo mv ./scripts/discogs-cli /usr/local/bin/discogs-cli
        ```

    -   **Option B: Create a Symbolic Link**
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill documents shell execution, package installation, network access to Discogs, and writing configuration/cache files, but declares no explicit tool scope or permissions. In an agent environment, this can lead to overbroad execution authority and weak user understanding of what the skill is allowed to do.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
This skill is a Go program and requires the Go toolchain to be installed.

**Installation (Debian/Ubuntu):**
`sudo apt-get update && sudo apt-get install -y golang-go`

## One-Time Setup
Confidence
83% confidence
Finding
The documentation tells users to run package installation with sudo, which requires elevated privileges and expands the consequences of mistakes, compromised package sources, or copy-paste misuse. While common in setup guides, encouraging privileged execution in a skill increases risk in agent-assisted environments where users may execute commands with less scrutiny.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill instructs the user to store a Discogs token in a local configuration file without warning about sensitivity, file permissions, or safer secret-handling methods. Tokens can grant API access to account data and actions, so careless storage increases the risk of credential disclosure from local compromise, backups, logs, or shared environments.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The command documentation says it fetches and displays/sends album art, which implies retrieval and presentation. However, the implementation additionally creates a workspace cache directory and writes the downloaded image to a local file, which is a broader behavior than the user-facing description suggests.

External Transmission

Medium
Category
Data Exfiltration
Content
}

		client := &http.Client{}
		url := fmt.Sprintf("https://api.discogs.com/releases/%d", releaseID)
		req, err := http.NewRequest("GET", url, nil)
		if err != nil {
			fmt.Println("Error creating request:", err)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
}

		client := &http.Client{}
		url := fmt.Sprintf("https://api.discogs.com/releases/%d", releaseID)
		req, err := http.NewRequest("GET", url, nil)
		if err != nil {
			fmt.Println("Error creating request:", err)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
}

		client := &http.Client{}
		url := fmt.Sprintf("https://api.discogs.com/releases/%d", releaseID)
		req, err := http.NewRequest("GET", url, nil)
		if err != nil {
			fmt.Println("Error creating request:", err)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
}

		client := &http.Client{}
		url := fmt.Sprintf("https://api.discogs.com/releases/%d", releaseID)
		req, err := http.NewRequest("GET", url, nil)
		if err != nil {
			fmt.Println("Error creating request:", err)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The command accepts a Discogs personal access token and persists it to the local configuration file via Viper without any visible protection, warning, or file-permission hardening. Storing secrets in plaintext configuration files increases the risk of token disclosure through local compromise, backups, shared home directories, or accidental file exposure.

Missing User Warnings

Low
Confidence
85% confidence
Finding
The README instructs users to store a Discogs username and personal access token in a local configuration file while only stating that it is stored 'securely' without explaining file permissions, encryption, or local exposure risks. This can mislead users into treating plaintext local secret storage as inherently safe, increasing the chance of credential leakage through backups, multi-user systems, or accidental file disclosure.

Missing User Warnings

Low
Confidence
86% confidence
Finding
The skill documentation includes a command that removes a release from the user's wantlist, which changes user data on Discogs. There is no warning, confirmation note, or caution that the command performs a deletion-like account modification.

Static analysis

No suspicious patterns detected.