Back to skill

Security audit

Soccer Cli

Security checks for vulnerabilities and agentic risk

Overview

This is a straightforward soccer stats CLI with disclosed API use, though users should protect the API key file and note that the Go build is not reproducibly pinned.

Before installing, treat the API-Football key as a secret, store the config file with restrictive permissions, and review or pin the Go dependencies because this package does not include module checksum metadata. The skill does not show hidden behavior or malicious activity in the inspected artifacts.

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
SKILL.md:36
Finding
API Key Stored Without Enforced Restrictive File Permissions## Vulnerability Details **File Location**: `SKILL.md:36-44` (also documented in `README.md:26-34`) **Vulnerability Type**: Plaintext secret stored with potentially insecure permissions **Risk Level**: Medium **Vulnerable Code Snippet**: ```bash mkdir -p ~/.config/soccer-cli touch ~/.config/soccer-cli/config.yaml ``` ```yaml apikey: YOUR_API_KEY_HERE ``` ### Technical Analysis The documented configuration procedure stores the API-Football key in a plaintext file but does not enforce owner-only permissions on either the configuration directory or file. The resulting permissions depend on the user's current `umask` and any preexisting directory permissions. For example, a common `umask` of `022` can create the file with mode `0644`, allowing other local users to read it when the home directory is traversable. The application subsequently reads this credential and transmits it in the `x-apisports-key` HTTPS request header. No hardcoded credential or transmission to an undeclared host was identified, but disclosure of the configuration file would expose the user's API credential. ### Attack Path 1. A user follows the documented commands to create `~/.config/soccer-cli/config.yaml`. 2. The file is created under a permissive `umask` or inside an inadequately protected home/configuration directory. 3. Another local account enumerates readable files under the victim's configuration directory. 4. The attacker reads the plaintext `apikey` value. 5. The attacker submits API-Football requests using the stolen key. Exploitation requires local access and filesystem permission to traverse the relevant parent directories. ### Impact Assessment An attacker may obtain the API-Football key and make requests under the victim's account. This can consume API quota, interfere with availability, and potentially cause account-level or billing consequences depending on the associated subscription. The issue does not grant operating- ...[truncated 80 chars]
Remediation
## Remediation Suggestions - Replace the documented creation procedure with commands that enforce owner-only access: ```bash install -d -m 700 "$HOME/.config/soccer-cli" install -m 600 /dev/null "$HOME/.config/soccer-cli/config.yaml" ``` - Update both `SKILL.md` and `README.md` so their instructions are consistent. - At runtime, inspect the configuration file's permission bits and reject or prominently warn about files readable or writable by group or other users. - Ensure the application does not print the API key in errors, diagnostics, or debug logs. - Document key rotation as the response to suspected configuration-file disclosure.

T08 · Insecure Dependencies

Warning
Location
install.sh:11
Finding
Unpinned Third-Party Go Dependencies and Missing Integrity Metadata## Vulnerability Details **File Location**: `install.sh:11-12`, with third-party imports in `cmd/root.go:6-7`, `cmd/game.go:9-10`, `cmd/scores.go:10-11`, and `cmd/squad.go:9-10` **Vulnerability Type**: Non-reproducible dependency resolution without committed checksums **Risk Level**: Medium **Vulnerable Code Snippet**: ```bash # Build the Go binary. This creates a 'soccer-cli' executable in the current directory. go build -o soccer-cli main.go ``` Representative third-party imports include: ```go import ( "github.com/spf13/cobra" "github.com/spf13/viper" ) ``` ```go import ( "github.com/olekukonko/tablewriter" "github.com/spf13/cobra" ) ``` The audited project contains no `go.mod` or `go.sum` file. ### Technical Analysis The installer builds code that imports Cobra, Viper, and Tablewriter, but the project does not commit module version constraints or checksum metadata. Consequently, the source tree does not define a reproducible, integrity-verifiable dependency graph. In a clean modern Go environment, the build may fail because no module definition is present. In an environment relying on external workspace configuration, GOPATH behavior, or preexisting module state, dependency selection can depend on uncontrolled local or remote state. This increases supply-chain exposure and prevents reviewers from verifying precisely which dependency versions are incorporated into the installed binary. No evidence was found that any named dependency is currently malicious. The risk arises from missing version and integrity controls rather than a confirmed compromised package. ### Attack Path 1. A user invokes `install.sh`. 2. The Go toolchain attempts to resolve project and third-party imports using environment-dependent module, workspace, cache, or GOPATH state. 3. An attacker compromises a dependency source, proxy, local module cache, workspace replacement, or another applicable dependency ...[truncated 996 chars]
Remediation
## Remediation Suggestions - Add and commit a canonical `go.mod` that pins reviewed direct dependency versions. - Generate and commit `go.sum` so downloaded module content is checked against expected hashes. - Ensure the module path matches the imports used by the project. - Build the complete module in read-only dependency mode: ```bash go build -mod=readonly -o soccer-cli . ``` - Run `go mod verify` in the installation or release process. - Review dependency updates and use automated vulnerability scanning such as `govulncheck`. - Produce signed or checksummed release artifacts if prebuilt binaries are distributed. - Avoid unreviewed `replace` directives and document any required Go workspace configuration.

T09 · Insecure Skill Coding Practices

Note
Location
cmd/squad.go:48
Finding
Unchecked API Statistics Slice Can Crash the Squad Command## Vulnerability Details **File Location**: `cmd/squad.go:48-50` and `cmd/squad.go:65-67` **Vulnerability Type**: Unchecked slice indexing of externally supplied API data **Risk Level**: Low **Vulnerable Code Snippet**: ```go for _, playerDetail := range homeTeam.Players { stats := playerDetail.Statistics[0] // Assuming one set of stats per player per game if stats.Games.Minutes > 0 { ``` ```go for _, playerDetail := range awayTeam.Players { stats := playerDetail.Statistics[0] if stats.Games.Minutes > 0 { ``` ### Technical Analysis The `Statistics` field is populated from the remote API response and is represented as a slice. The command directly accesses element zero without verifying that the slice contains an element. A syntactically valid response containing a player with an empty or omitted `statistics` array therefore causes a Go index-out-of-range panic. Although the HTTP client restricts requests to a fixed HTTPS API host, malformed upstream data, an upstream service defect, or a compromised API response can trigger the failure. The issue is limited to process availability because no memory corruption primitive results from Go's bounds checking. ### Attack Path 1. The user runs `soccer-cli squad` with a fixture ID. 2. The API returns at least two team entries, satisfying the existing team-count check. 3. At least one player entry contains an empty or omitted `statistics` array. 4. The loop evaluates `playerDetail.Statistics[0]`. 5. Go raises an index-out-of-range panic and terminates the CLI process. An attacker would need influence over the API response or upstream data. Ordinary incomplete data may also trigger the same condition without malicious action. ### Impact Assessment The affected command terminates before completing output, resulting in a local denial of service for that invocation. Repeated malformed responses can make the squad functionality unavailable. The issue ...[truncated 104 chars]
Remediation
## Remediation Suggestions - Validate the slice before accessing its first element: ```go for _, playerDetail := range homeTeam.Players { if len(playerDetail.Statistics) == 0 { continue } stats := playerDetail.Statistics[0] if stats.Games.Minutes > 0 { // Append the validated statistics. } } ``` - Apply the same validation to both home and away player loops. - Consider displaying an explicit “statistics unavailable” value instead of silently skipping incomplete entries. - Add unit tests covering omitted, null, and empty `statistics` arrays. - Validate the decoded API response before passing it to presentation logic.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (5)

Session Persistence

Medium
Category
Rogue Agent
Content
3.  **Configure API Key:**
    The CLI needs a free API key from [API-Football](https://www.api-football.com/).

    Create a configuration file at `~/.config/soccer-cli/config.yaml`:
    ```bash
    mkdir -p ~/.config/soccer-cli
    touch ~/.config/soccer-cli/config.yaml
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
3.  **Configure API Key:**
    The CLI needs a free API key from [API-Football](https://www.api-football.com/).

    Create a configuration file at `~/.config/soccer-cli/config.yaml`:
    ```bash
    mkdir -p ~/.config/soccer-cli
    touch ~/.config/soccer-cli/config.yaml
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			fmt.Println("Config file not found. Please create one at ~/.config/soccer-cli/config.yaml")
			fmt.Println("Example:\napikey: YOUR_API_KEY_HERE")
			os.Exit(1)
		} else {
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Missing User Warnings

Low
Confidence
84% confidence
Finding
This markdown file tells users to create a config file containing a live API key, but it does not include any warning about protecting that file, avoiding commits, or treating the key as sensitive. For markdown files, omissions around behaviors affecting privacy or credentials handling can warrant a missing-warning finding.

Missing User Warnings

Low
Confidence
87% confidence
Finding
This code performs outbound network requests and includes a credential in the request header via `x-apisports-key`. There is no user-facing log, comment, docstring, or confirmation indicating that requests send authentication data to an external service.

Static analysis

No suspicious patterns detected.