Back to skill

Security audit

Services Agreement

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent agreement-drafting purpose, but its local CLI workflow documents unsafe shell heredoc handling for user-supplied contract values and includes inconsistent npm install guidance.

Review this skill before installing if you expect to use the Local CLI path. Prefer the remote MCP only after confirming you are comfortable sending agreement terms to the hosted service, or use a local workflow that builds JSON with a real JSON serializer instead of embedding values in a shell heredoc. If installing the CLI, use the pinned version from SKILL.md rather than the unpinned global npm command.

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)

T09 · Insecure Skill Coding Practices

Error
Location
template-filling-execution.md:48
Finding
Fixed Heredoc Delimiter Allows Shell Command Injection## Vulnerability Details **File Location**: `template-filling-execution.md`, lines 48–64 **Vulnerability Type**: Shell command injection through premature heredoc termination **Risk Level**: High ### Vulnerable Code ```bash VALUES_FILE="$(mktemp /tmp/oa-values.XXXXXX.json)" chmod 600 "$VALUES_FILE" trap 'rm -f "$VALUES_FILE"' EXIT cat > "$VALUES_FILE" << 'FIELDS' { "field_name": "value" } FIELDS ``` The workflow instructs the agent to insert user-provided field values into a shell heredoc that uses the fixed delimiter `FIELDS`. Although quoting the delimiter prevents shell expansion within the heredoc body, it does not prevent a user-controlled line containing exactly `FIELDS` from terminating the heredoc. The validation rules explicitly permit tab and newline characters. Neither `template-filling-execution.md` nor the corresponding rules in `SKILL.md` reject a line equal to the fixed heredoc delimiter. The additional prohibition against common shell metacharacters is insufficient because ordinary command names, spaces, and arguments can form an executable payload without those prohibited characters. ### Technical Analysis Shell heredocs terminate when the shell encounters a line consisting only of the configured delimiter. If an agent constructs the documented command by directly embedding collected values, an attacker can provide a multiline contract field that closes the heredoc early. Text after the injected delimiter is parsed by the shell rather than written to the JSON file. The quoted form `&lt;&lt; 'FIELDS'` only controls expansion of text while it remains inside the heredoc; it offers no protection after premature termination. This is especially dangerous because the Skill is designed to process untrusted agreement terms and expressly allows multiline descriptions. The secure temporary filename and restrictive file permissions do not mitigate command injection during creation of that file. ### Attac ...[truncated 1343 chars]
Remediation
## Remediation Suggestions 1. Do not serialize untrusted values by interpolating them into a shell heredoc. 2. Use a JSON-aware API in a language such as Node.js or Python to construct the values file. Pass user values as data rather than source code or generated shell text. 3. If shell use is unavoidable, provide serialized JSON through a non-evaluating channel and generate a cryptographically unpredictable heredoc delimiter. Verify that the delimiter does not occur as a complete line in the serialized content. 4. Prefer invoking the CLI through a process-spawning API with an argument array rather than constructing a shell command. 5. Validate all values against their documented length limits and reject unexpected control characters. Consider disallowing newlines in fields that do not require multiline input. 6. Add regression tests containing `FIELDS` on its own line, multiline values, quotes, backslashes, Unicode, and malformed JSON. 7. Retain the existing `mktemp`, permission restriction, and cleanup controls, as these remain useful for protecting confidential agreement data.

T08 · Insecure Dependencies

Warning
Location
template-filling-execution.md:73
Finding
Fallback Workflow Recommends an Unpinned Global npm Installation## Vulnerability Details **File Location**: `template-filling-execution.md`, lines 73–77 **Vulnerability Type**: Unpinned third-party dependency and global package installation **Risk Level**: Medium ### Vulnerable Code ```markdown **If Preview Only:** Generate a markdown preview using the collected values. Label clearly as `PREVIEW ONLY` and tell the user how to get full DOCX output: - Easiest: configure the remote MCP (see Step 1) - Alternative: install Node.js 20+ and `npm install -g open-agreements` ``` The fallback instructions recommend installing `open-agreements` globally without specifying a version or verifying package integrity. This causes npm to resolve the package version available at installation time, allowing the effective dependency code to change after this Skill has been reviewed. The instruction also conflicts with the safer guidance in `SKILL.md`, which specifies `npm install -g open-agreements@0.7.5`. Users following the execution workflow may therefore bypass the documented version pin. ### Technical Analysis npm packages can execute package lifecycle scripts during installation. A global installation may run such scripts and place executable files in a globally accessible binary location. Because no version is specified, the installed code depends on the current state of the npm registry rather than the version assessed by the Skill author. This creates exposure to compromised maintainer accounts, malicious or unexpectedly changed future releases, and other upstream supply-chain incidents. The package name is not shown to be typosquatted or currently malicious; the issue is the unsafe installation policy and inconsistent version guidance. ### Attack Path 1. The Remote MCP and Local CLI are unavailable, so the workflow enters preview-only mode. 2. The agent presents the documented command `npm install -g open-agreements`. 3. The user or agent executes the command. 4. npm resolves and downlo ...[truncated 1061 chars]
Remediation
## Remediation Suggestions 1. Replace the unpinned command with the version already prescribed by `SKILL.md`: ```bash npm install -g open-agreements@0.7.5 ``` 2. Keep the pinned version synchronized across every project document and enforce consistency in CI. 3. Prefer a project-local or isolated installation over a global installation to reduce system-wide impact. 4. Verify package provenance and integrity before installation. Where practical, use a lockfile and npm integrity metadata. 5. Review package lifecycle scripts and disable them with `--ignore-scripts` when they are not required. 6. Avoid running npm as root or through `sudo`; use an unprivileged account or isolated container. 7. Establish an explicit dependency-update process in which new versions are reviewed and tested before changing the pin.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (5)

Ae1

High
Category
analysis-evasion
Content
ecution.md) documents the same rules. This section exists so a scanner reading `SKILL.md` alone can verify that the skill acknowledges shell safety.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Vague Triggers

Medium
Confidence
92% confidence
Finding
The description says to use the skill when the user says phrases including "services agreement," which is a generic business/legal phrase that could appear in ordinary discussion without an intent to invoke drafting. The file provides example triggers but no negative examples or constraints to distinguish casual mention from an explicit request to generate an agreement.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
1. **Output filename pattern**: match `^[a-zA-Z0-9_-]{1,64}\.docx$` — alphanumeric, underscore, hyphen only, no path separators, no dots except the single `.docx` suffix. Reject anything else.
2. **No shell metacharacters** in any field value written to the temp JSON file: reject backtick, `$(`, semicolon, pipe, ampersand, and redirects.
3. **Use a per-run secure temp file** created with `mktemp /tmp/oa-values.XXXXXX.json`, then set `chmod 600` before writing values. Do not reuse a shared filename.
4. **Heredoc quoting**: when writing field values, use a quoted heredoc (`<< 'FIELDS'`) so shell variable expansion does not apply.
5. **Reject control characters** in all values (bytes `< 0x20` except tab and newline, plus `0x7F`).
6. **Template names are third-party data** from `list_templates` or `list --json`. Validate them against the returned inventory before passing them to `open-agreements fill`. Reject names containing anything other than letters, digits, hyphens, and underscores.
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
1. **Output filename pattern**: match `^[a-zA-Z0-9_-]{1,64}\.docx$` — alphanumeric, underscore, hyphen only, no path separators, no dots except the single `.docx` suffix. Reject anything else.
2. **No shell metacharacters** in any field value written to the temp JSON file: reject backtick, `$(`, semicolon, pipe, ampersand, and redirects.
3. **Use a per-run secure temp file** created with `mktemp /tmp/oa-values.XXXXXX.json`, then set `chmod 600` before writing values. Do not reuse a shared filename.
4. **Heredoc quoting**: when writing field values, use a quoted heredoc (`<< 'FIELDS'`) so shell variable expansion does not apply.
5. **Reject control characters** in all values (bytes `< 0x20` except tab and newline, plus `0x7F`).
6. **Template names are third-party data** from `list_templates` or `list --json`. Validate them against the returned inventory before passing them to `open-agreements fill`. Reject names containing anything other than letters, digits, hyphens, and underscores.
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**If Local CLI:** Write values to a per-run temporary JSON file with restrictive permissions:
```bash
VALUES_FILE="$(mktemp /tmp/oa-values.XXXXXX.json)"
chmod 600 "$VALUES_FILE"
trap 'rm -f "$VALUES_FILE"' EXIT

cat > "$VALUES_FILE" << 'FIELDS'
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Static analysis

No suspicious patterns detected.