Back to skill

Security audit

Coda Packs

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent Coda Packs management helper with expected API-token use and Pack mutation actions, but users should be careful with unpinned npm tooling, command-line tokens, and forced deletion.

Install only if you are comfortable giving the tool a Coda API token with Pack-management permissions. Prefer CODA_API_TOKEN over --token, avoid --force except in deliberate automation, double-check Pack IDs before deletion, and pin or locally lock @codahq/packs-sdk before running the npm/npx development 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
SKILL.md:91
Finding
Unpinned Coda Pack SDK Installation and Execution<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:91-104` and `SKILL.md:187-189` **Vulnerability Type**: Unpinned third-party dependency installation and execution **Risk Level**: Medium ### Vulnerable Code ```bash # Install Pack SDK npm install -g @codahq/packs-sdk # Initialize Pack project npx @codahq/packs-sdk init karakeep-pack # Develop your Pack (edit pack.ts) # See: https://coda.io/packs/build/latest/guides/quickstart/ # Build and upload npx @codahq/packs-sdk build npx @codahq/packs-sdk upload # Submit to Gallery (when ready) npx @codahq/packs-sdk release ``` Additional instructions repeat the unpinned execution: ```bash 1. Use Pack SDK CLI: `npx @codahq/packs-sdk init karakeep-pack` 2. Implement Karakeep API integration (see https://docs.karakeep.app/api/) 3. Build and upload: `npx @codahq/packs-sdk build && npx @codahq/packs-sdk upload` ``` ### Technical Analysis The Skill instructs users to install and execute `@codahq/packs-sdk` without pinning an audited version or verifying package integrity. Both `npm install -g` and `npx` can retrieve mutable content from the npm registry. Consequently, the code executed by a user may differ from the code available when the Skill was audited. The package name and linked Coda documentation are consistent with the declared functionality, and the project does not automatically execute these commands. Nevertheless, following the documented workflow creates a supply-chain trust boundary that is not constrained by a lockfile, an exact version, or integrity verification. Global installation also expands the package's local footprint. ### Attack Path 1. An attacker compromises the npm package publisher, a transitive dependency, or the relevant registry delivery path. 2. The attacker publishes a malicious version under the same package name or compromises a version selected by the unpinned dependency resolution. 3. A user follows the Skill instructions and runs `npm install -g @codahq/packs-sdk` ...[truncated 864 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the SDK to an exact, reviewed version, for example: ```bash npx --yes @codahq/packs-sdk@<audited-version> build ``` 2. Prefer a project-local development dependency over global installation: ```bash npm install --save-dev --save-exact @codahq/packs-sdk@<audited-version> ``` 3. Commit and enforce a lockfile, and use `npm ci` for reproducible installation. 4. Verify package provenance, registry source, and integrity before execution. 5. Review transitive dependencies and npm lifecycle scripts for the pinned release. 6. Run dependency tooling as an unprivileged user and never recommend elevated installation. 7. Update every SDK command in `SKILL.md` to reference the same audited version. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/coda_packs_cli.py:366
Finding
Coda API Token Can Be Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/coda_packs_cli.py:46-50`, `scripts/coda_packs_cli.py:366`, and `scripts/coda_packs_cli.py:444-445` **Vulnerability Type**: Sensitive credential exposure through process arguments **Risk Level**: Medium ### Vulnerable Code Token selection accepts a value provided through the command line: ```python self.token = token or os.environ.get("CODA_API_TOKEN") if not self.token: raise CodaAPIError( "Coda API token required. Set CODA_API_TOKEN environment variable " "or pass --token." ) ``` The command-line option is explicitly registered: ```python parser.add_argument("--token", help="Coda API token (or set CODA_API_TOKEN env var)") ``` The parsed argument is then passed to the API client: ```python try: client = CodaClient(token=args.token) args.func(args, client) ``` ### Technical Analysis Command-line arguments are not an appropriate transport for long-lived secrets. A token supplied as `--token <value>` can be recorded in shell history, process listings, system audit telemetry, terminal logs, CI/CD logs, command wrappers, or diagnostic reports. The client subsequently uses this token as a Bearer credential for Coda API requests. Sending the credential to the fixed HTTPS endpoint `https://coda.io/apis/v1` is necessary for the declared Pack-management functionality and was not found to be unrelated exfiltration. The vulnerability is the additional argv-based credential input mechanism, not the authenticated HTTPS request itself. ### Attack Path 1. A user invokes the CLI with a command such as: ```bash python scripts/coda_packs_cli.py --token SECRET packs list ``` 2. The complete command is retained in shell history, captured by an automation log, or exposed through process metadata while the command is running. 3. A local user, log reader, monitoring integration, or compromised process obtains the token. 4. The attacker submits authenticated requests to t ...[truncated 636 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `--token` command-line option and the corresponding `args.token` flow. 2. Obtain the token from `CODA_API_TOKEN` or a platform credential store. 3. If interactive entry is required, use a hidden prompt: ```python import getpass token = os.environ.get("CODA_API_TOKEN") or getpass.getpass("Coda API token: ") ``` 4. Prefer an operating-system keychain or secret manager for persistent credentials. 5. Ensure exception messages, request logging, and debug output never include the Authorization header or token. 6. Document that tokens must not be placed in shell commands, scripts, URLs, or CI log output. 7. Recommend narrowly scoped tokens and periodic rotation so that exposure has limited impact. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (24)

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
The skill instructs users to run `npx @codahq/packs-sdk` without pinning an exact version, which allows whatever package version is current at execution time to be fetched and executed. If the upstream package is compromised, a malicious release is published, or behavior changes unexpectedly, this can lead to arbitrary code execution on the user's machine.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
This command uses `npx` to execute `@codahq/packs-sdk` without an exact version pin. Unpinned package execution creates a supply-chain risk because the resolved code may change over time or be replaced by a malicious upstream release.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
The documented `npx` invocation pulls and runs a package without version pinning. That exposes users to upstream compromise and non-deterministic behavior, especially risky for tooling that is granted access to local code and credentials.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
The install instruction `npm install -g @codahq/packs-sdk` does not pin a specific version, so users will receive the latest available package at install time. This increases supply-chain exposure and makes builds and behavior non-reproducible.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
Running `npx @codahq/packs-sdk build` without version pinning executes code resolved at runtime from the registry. A malicious or altered upstream release could execute arbitrary code and affect local source, secrets, or build outputs.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
This unpinned `npx` command carries the same supply-chain risk as other runtime package executions. Because the command uploads or interacts with Pack tooling, compromise could impact both the local environment and remote resources accessible via credentials.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
The release command executes an unpinned package from the npm ecosystem, which is a classic supply-chain risk. The danger is elevated by the fact that release workflows often run in privileged developer or CI environments with access to source code and tokens.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
# Delete Pack (requires confirmation)
python scripts/coda_packs_cli.py packs delete my-pack-id
# Or skip confirmation: --force
```

### Pack ID Resolution
Confidence
85% confidence
Finding
Documenting a `--force` flag to skip delete confirmation weakens an important guardrail around an irreversible operation. In an agent-driven or scripted context, this can enable accidental or unauthorized destructive actions with less user friction, especially if a pack name/ID is resolved incorrectly.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
|-----------|------|--------------|
| **Delete Pack** | Irreversible | "Delete Pack 'X'? This cannot be undone." |

### No Confirmation Required

- **Create Pack**: Safe, reversible
- **List/Get Packs**: Read-only
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
The initialization command references `npx @codahq/packs-sdk` without a fixed version, allowing arbitrary future code changes to be pulled into the environment. This is a reproducibility and supply-chain integrity issue rather than an overtly malicious instruction.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
This second command on the same line also runs an unpinned package from npm, creating the same supply-chain exposure. Combining multiple unpinned executions in one shell line increases the blast radius if the package is malicious or unexpectedly changed.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
print_json(pack)
    
    def create(self, args):
        """Create new Pack (no confirmation required)."""
        payload = {
            "name": args.name,
            "description": args.description or ""
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
print_json(pack)
    
    def create(self, args):
        """Create new Pack (no confirmation required)."""
        payload = {
            "name": args.name,
            "description": args.description or ""
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
"""
    )
    parser.add_argument("--token", help="Coda API token (or set CODA_API_TOKEN env var)")
    parser.add_argument("--force", action="store_true", help="Skip confirmations (use with caution)")
    
    subparsers = parser.add_subparsers(dest="command_group")
Confidence
85% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The CLI help text says --readme is a 'Path to README file', which implies the program will open that file and use its contents. In create(), however, args.readme is copied directly into the API payload at L281-L282 with no file read, so the implementation contradicts the documented behavior and may cause users to transmit an unintended filesystem path string to the remote API.

Missing User Warnings

Low
Confidence
82% confidence
Finding
This code reads the sensitive CODA_API_TOKEN from the environment and attaches it as a Bearer token to all outbound API requests. Although the module docstring mentions setting the token, there is no user-facing warning at the point of execution that credentials will be sent over the network to Coda.

Static analysis

No suspicious patterns detected.