Back to skill

Security audit

Tally

Security checks for vulnerabilities and agentic risk

Overview

This is a straightforward Tally API guide, but users should be careful because it uses a Tally API key and can read submissions or update live forms.

Install only if you intend the agent to work with your Tally account. Keep the Tally API key least-privileged, avoid retrieving submissions unless authorized, duplicate or back up forms before PATCH updates, and replace the fixed /tmp file paths with private files you control.

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

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:235
Finding

Predictable Temporary Files Permit Symlink Attacks and Form-Content Tampering

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 235–244
Vulnerability Type: Predictable and insecure temporary-file usage
Risk Level: Medium

Vulnerable Code

bash
# Backup first
curl -s "https://api.tally.so/forms/{ID}" \
  -H "Authorization: Bearer $TALLY_KEY" > /tmp/backup.json

# Update
curl -s "https://api.tally.so/forms/{ID}" \
  -X PATCH \
  -H "Authorization: Bearer $TALLY_KEY" \
  -H "Content-Type: application/json" \
  -d @/tmp/form.json

Technical Analysis

The documented commands use the globally predictable paths /tmp/backup.json and /tmp/form.json. On multi-user systems, files in /tmp may be created, replaced, or linked by another local user before the commands execute.

Shell output redirection follows symbolic links. If an attacker creates /tmp/backup.json as a symbolic link to another file writable by the victim, the backup command can overwrite that target with the API response. The backup may also contain sensitive form configuration or respondent-related information and could remain accessible if its permissions are affected by an unsafe process umask.

The update operation reads its request body directly from the fixed /tmp/form.json path without verifying file ownership, permissions, type, or integrity. A local attacker able to create or replace that file can cause attacker-controlled form content to be submitted using the victim's authenticated Tally API credentials.

Attack Path

Backup symlink attack:

  1. A local attacker predicts that the victim will execute the documented command.
  2. The attacker creates /tmp/backup.json as a symbolic link to a file writable by the victim.
  3. The victim runs the backup command.
  4. Shell redirection follows the symbolic link and overwrites the target with the Tally API response.
  5. Depending on the selected target, this can corrupt user-owned files or alter user-level configuration.

**Update-c ...[truncated 1420 chars]

Remediation
View remediation

Remediation Suggestions

Create a private temporary directory with an unpredictable name, enforce restrictive permissions, and remove it automatically:

bash
set -euo pipefail
umask 077

tmp_dir="$(mktemp -d)"
trap 'rm -rf -- "$tmp_dir"' EXIT

backup_file="$tmp_dir/backup.json"
form_file="$tmp_dir/form.json"

curl --fail --silent --show-error \
  "https://api.tally.so/forms/{ID}" \
  -H "Authorization: Bearer $TALLY_KEY" \
  --output "$backup_file"

# Create or securely copy the intended update into "$form_file".
# Validate its ownership, regular-file status, permissions, and JSON structure.
test -f "$form_file" && test ! -L "$form_file"
jq empty "$form_file"

curl --fail --silent --show-error \
  "https://api.tally.so/forms/{ID}" \
  -X PATCH \
  -H "Authorization: Bearer $TALLY_KEY" \
  -H "Content-Type: application/json" \
  --data-binary "@$form_file"

Additional hardening measures should include:

  • Never use fixed filenames in shared temporary directories.
  • Verify that update input is a regular file, not a symbolic link.
  • Ensure the executing user owns the input file and that it is not writable by other users.
  • Validate the JSON schema and expected form identifier before submission.
  • Use curl --fail --silent --show-error so HTTP and transport failures are not silently treated as success.
  • Store backups in a protected, user-controlled directory if they must persist.
  • Apply least privilege to the Tally API key and rotate it if unauthorized form changes are suspected.
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 (11)

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · SKILL.md (reported line 4)May include surrounding context.

md
---
name: tally
version: 1.0.0
description: Create and edit Tally forms via API. Use when building surveys, feedback forms, or questionnaires programmatically. Supports all question types including text inputs, multiple choice, checkboxes, ratings (via workaround), and more.
---

# Tally Forms API

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 21)May include surrounding context.

md
| Action | Method | Endpoint |
|--------|--------|----------|
| List forms | GET | `https://api.tally.so/forms` |
| Get form | GET | `https://api.tally.so/forms/{id}` |
| Update form | PATCH | `https://api.tally.so/forms/{id}` |
| Get submissions | GET | `https://api.tally.so/forms/{id}/submissions` |

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 22)May include surrounding context.

md
| Action | Method | Endpoint |
|--------|--------|----------|
| List forms | GET | `https://api.tally.so/forms` |
| Get form | GET | `https://api.tally.so/forms/{id}` |
| Update form | PATCH | `https://api.tally.so/forms/{id}` |
| Get submissions | GET | `https://api.tally.so/forms/{id}/submissions` |

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 23)May include surrounding context.

md
| Action | Method | Endpoint |
|--------|--------|----------|
| List forms | GET | `https://api.tally.so/forms` |
| Get form | GET | `https://api.tally.so/forms/{id}` |
| Update form | PATCH | `https://api.tally.so/forms/{id}` |
| Get submissions | GET | `https://api.tally.so/forms/{id}/submissions` |

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 24)May include surrounding context.

md
| Action | Method | Endpoint |
|--------|--------|----------|
| List forms | GET | `https://api.tally.so/forms` |
| Get form | GET | `https://api.tally.so/forms/{id}` |
| Update form | PATCH | `https://api.tally.so/forms/{id}` |
| Get submissions | GET | `https://api.tally.so/forms/{id}/submissions` |

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 236)May include surrounding context.

md
| Action | Method | Endpoint |
|--------|--------|----------|
| List forms | GET | `https://api.tally.so/forms` |
| Get form | GET | `https://api.tally.so/forms/{id}` |
| Update form | PATCH | `https://api.tally.so/forms/{id}` |
| Get submissions | GET | `https://api.tally.so/forms/{id}/submissions` |

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 240)May include surrounding context.

md
| Action | Method | Endpoint |
|--------|--------|----------|
| List forms | GET | `https://api.tally.so/forms` |
| Get form | GET | `https://api.tally.so/forms/{id}` |
| Update form | PATCH | `https://api.tally.so/forms/{id}` |
| Get submissions | GET | `https://api.tally.so/forms/{id}/submissions` |

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 247)May include surrounding context.

md
| Action | Method | Endpoint |
|--------|--------|----------|
| List forms | GET | `https://api.tally.so/forms` |
| Get form | GET | `https://api.tally.so/forms/{id}` |
| Update form | PATCH | `https://api.tally.so/forms/{id}` |
| Get submissions | GET | `https://api.tally.so/forms/{id}/submissions` |

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill documents a submission-retrieval endpoint without warning that form submissions may contain personal, sensitive, or regulated data. This omission increases the risk of unnecessary collection, exposure, or mishandling of respondent data by users who may not appreciate the privacy implications.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill provides write-capable PATCH examples against live Tally forms but does not warn that these operations can overwrite production configuration. A user following the instructions could unintentionally destroy or alter a live form, causing availability and integrity issues for surveys and data collection workflows.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 236)May include surrounding context.

md
TALLY_KEY=$(cat ~/.config/tally/api_key)

# Backup first
curl -s "https://api.tally.so/forms/{ID}" \
  -H "Authorization: Bearer $TALLY_KEY" > /tmp/backup.json

# Update

Static analysis

No suspicious patterns detected.