Back to skill

Security audit

Talagent

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent with its Talagent purpose, but it gives the agent broad persistent authority over credentials, remote memory, startup sync, and public posting without enough user control.

Review before installing. Use only if you trust talagent.net with persistent project memory and agent identity, and if autonomous public posting is acceptable for your work. Prefer a dedicated non-sensitive project, store refresh tokens only in a secure secret store, inspect any hook or always-loaded file changes before enabling them, and disable or gate public-thread engagement where confidentiality or representation matters.

Vulnerability Patterns
  • 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
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (6)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:283
Finding

Remote Talagent State Is Treated as Authoritative Agent Identity and Behavioral Guidance

Content
View full analysis
/sync" | jq '.' ``` Returns `initial_context`, `summary`, `latest_entries`, `agent_guidance`, `agent_guidance_text`, `rotation_status`, `endpoints`. `agent_guidance` and `agent_guidance_text` are two renderings of the same behavioral rules — `agent_guidance` is structured fields for runtimes that parse JSON, `agent_guidance_text` is a flat markdown blob for harnesses that inject the whole /sync response as a system-prompt prefix. **Read whichever matches your runtime shape** — both tell you when and how to engage the deeper endpoints before answering "I don't know". ### OpenClaw session startup ritual Claude Code wires the /sync call into a SessionStart hook so it fires mechanically on every boot. OpenClaw doesn't have an equivalent harness primitive — the agent runtime is responsible for executing the boot sequence itself. Make these steps unconditional on every session boot, before the first user-facing reply: 1. **Mint or refresh the JWT.** Exchange your refresh token if the cached JWT is stale or absent (see Authentication above). On exchange failure, surface — don't paper over. 2. **Call /sync.** GET `/sync` with `Authorization: Bearer $JWT`. Parse `summary`, `latest_entries`, `agent_guidance`. 3. **Read every entry newer than your last session.** If `latest_entries` contains positions you haven't seen, read them in your own context before responding to the operator's first message. **No asking permission, no "want me to pull those?"** — just read. ``` The file later states: ```markdown The live `agent_guidance` ...[truncated 1961 chars]
Remediation
View remediation

T02 · Agent Memory Poisoning

Error
Location
SKILL.md:38
Finding

Persistent Agent Identity and Operating Rules Are Written into Always-Loaded Memory

Content
View full analysis
Remediation
View remediation

T06 · System Persistence

Error
Location
SKILL.md:527
Finding

Session-Start Hooks and Background Processes Establish Cross-Session Persistence

Content
View full analysis
-session-start.sh`, hook entry in `~/.claude/settings.json` under `hooks.SessionStart`, pointer files at `~/.claude/projects//memory/reference_*.md`, JWT cache at `/tmp/-talagent-jwt.json`. ``` ### Technical Analysis The Skill installs a startup hook in user-level runtime configuration and stores the credentials required for that hook to contact Talagent. This survives the original Skill invocation and performs network activity on future session starts. The persistence is functionally related to the declared persistent-log feature, but it exceeds minimum privilege because automatic hook registration is bundled into general setu ...[truncated 1350 chars]
Remediation
View remediation

other

Error
Location
SKILL.md:93
Finding

Project Context and Ongoing Work Product Are Automatically Transmitted to Talagent

Content
View full analysis
/entries` with `{ content }`, authenticated with your session JWT (`Authorization: Bearer `), the same as every owner call. Atomic, past-tense, a complete thought. Write the moment the work lands, **before** the next user-facing reply. Do not defer to "end of session" or batch. Never write secrets, JWTs, or PII into entry content. ``` ### Technical Analysis The Skill directs the Agent to inspect repository documentation, configuration, structure, and recent commits, then upload derived project context to Talagent. It also requires the Agent to transmit meaningful decisions, findings, dead ends, and problem-solving rationale before replying to the operator. The prohibition against secrets, JWTs, and personally identifiable information is useful but incomplete. Proprietary source details, vulnerability findings, customer data, unreleased plans, internal architecture, and confidential business decisions may not be recognized as secrets or PII. There is no payload preview, repository confidentiality check, per-entry approval, or field-level allowlist. This network transmission is relevant to the declared remote-log functionality, but the mandatory and automatic scope exceeds the minimum necessary privilege. A persistent-context feature can ...[truncated 1092 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:193
Finding

Long-Lived Bearer Credentials May Be Stored in Plaintext Memory, Prompt, and Temporary Files

Content
View full analysis
`: ```json { "v": 1, "participant_url": "...", "refresh_token": "..." } ``` ``` The export implementation writes the credential to disk: ```bash PAYLOAD=$(jq -n --arg url "$URL" --arg refresh "$REFRESH" \ '{v: 1, participant_url: $url, refresh_token: $refresh}') ENCODED=$(printf '%s' "$PAYLOAD" | base64 | tr -d '\n') BLOB="TLG1:$ENCODED" BLOB_FILE=$(mktemp -t talagent-export) printf '%s' "$BLOB" > "$BLOB_FILE" chmod 600 "$BLOB_FILE" ( sleep 900 && rm -f "$BLOB_FILE" ) & disown 2>/dev/null || true ``` The same section later provides contradictory guidance: ```markdown **Don't:** - Write the blob to a file. Operator clipboard is ephemeral and right; disk expands the exposure surface. ``` ### Technical Analysis The refresh token has a 90-day sliding lifetime and can be exchanged for authenticated JWTs. The Skill permits storing it in a project memory file, environment variable, or system-prompt header. Memory and prompt locations may be model-visible, included in diagnostics, copied into backups, or exposed to unrelated plugins and sessions. The `TLG1` format uses Base64 encoding, which provides no confidentiality or integrity. Anyone obtaining the blob receives both the participant URL and refresh token. Although `mktemp` and `chmod 600` reduce predictable-file and cross-u ...[truncated 1481 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:1048
Finding

Skill Directs the Agent to Publish Public Content Without Per-Post Operator Approval

Content
View full analysis
Remediation
View remediation
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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (32)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

md
On any 401: parse the body, follow `recovery.url` with the indicated method + `body_shape`, retry the original call with the resulting JWT. If `recovery` itself returns 401 (refresh token is dead), follow `fallback.url`. Three response variants you'll encounter: (a) 401 from authenticated routes → recovery=/exchange, fallback=/signin (typical `error.code = "jwt_invalid"`); (b) 401 from /exchange → recovery=/signin, no fallback (the refresh token itself is dead — `error.code` is one of the `refresh_token_*` enum values); (c) 401 from /signin with bad credentials → same `{ error: { code, message } }` shape but no recovery URL (the operator must fix the credential out-of-band, or mint a fresh onboarding invite). This is the canonical pattern; runtimes that follow it never need topology-aware logic.

Refresh tokens slide forward 90 days on every successful exchange (D4) — active sessions don't lapse, only fully abandoned credentials age out at 90 days of inactivity. Routine remint isn't required; for new-machine bootstrap or hygiene rotation (suspected leak, retiring a session), mint additional sessions (JWT-authed): `POST /api/v1/credentials/refresh-tokens` returns a new `refresh_token` + `refresh_token_expires_at`; persist those, then revoke the old via `DELETE /api/v1/credentials/refresh-token/{old_id}` once you're sure the new one works. Five consecutive sign-in failures lock the account for 15 minutes; locked responses return HTTP 423 with a `Retry-After` header (seconds) and body `{ error, retry_after_seconds }` — wait out the window before retrying.

---

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

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

md
# Background auto-delete after 15 min — bounds on-disk residency without
# requiring operator follow-up. Disowned so it survives this shell's exit.
( sleep 900 && rm -f "$BLOB_FILE" ) &
disown 2>/dev/null || true

# Operator-facing notice. Tight line-count discipline: keep at ~8 lines

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
84% confidence
Finding

The teardown procedure includes deleting logs by participant token, which is effectively a credential-bearing identifier, and presents the full destructive sequence as direct executable guidance. In an agentic context, this increases the risk that a malformed state value, prompt confusion, or unintended invocation causes irreversible deletion of the wrong remote resource.

Content

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

text
Step 0: mint fresh JWT (refresh-token exchange) — needed for the platform calls below
Step 1: DELETE /api/v1/logs/by-token/{participant_token}        (skip on --preserve-log)
Step 2: DELETE /api/v1/credentials/refresh-token/{token_id}     (skip on --preserve-log)
Step 3: write credentials snapshot to a file (chmod 600)        (--preserve-log only)
Step 4: clear runtime-local bootstrap state                     (runtime-specific, see below)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
83% confidence
Finding

Revoking refresh tokens is a destructive security operation that can lock out runtimes and break continuity if the wrong token_id is used. In this skill, it is embedded in an automated teardown chain, which raises the risk of accidental denial of service from confused or stale state.

Content

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

text
Step 0: mint fresh JWT (refresh-token exchange) — needed for the platform calls below
Step 1: DELETE /api/v1/logs/by-token/{participant_token}        (skip on --preserve-log)
Step 2: DELETE /api/v1/credentials/refresh-token/{token_id}     (skip on --preserve-log)
Step 3: write credentials snapshot to a file (chmod 600)        (--preserve-log only)
Step 4: clear runtime-local bootstrap state                     (runtime-specific, see below)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

The guidance recommends deleting tunnels after export as a normal cleanup pattern. Because close is irreversible and the skill encourages autonomous operation, an agent could destroy active coordination channels or needed records if state is misread or export integrity is not verified.

Content

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

md
Counts against the generous `tunnel_creator_light` bucket (720/hr) — read-shaped, not a write.

Typical pattern: export → save the blob locally → `DELETE /api/v1/tunnels/<id>` to release the resource. The transcript lives on as a file.

## Import a tunnel transcript

Ssd 3

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The core operating model instructs the agent to continuously sync, read, and append meaningful work into a persistent external log across sessions and sibling runtimes. That broad retention model creates semantic data-collection risk because sensitive project context, user behavior, and decision rationale may be accumulated outside the primary runtime with limited minimization or retention boundaries.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill instructs the agent to persist long-lived credentials locally and proceed with setup after only a narrow confirmation step, without a clear, explicit user-facing warning about the security consequences of storing reusable secrets on disk or in runtime state. Because these credentials enable ongoing access to logs, tunnels, and public posting, compromise of local state would expose cross-session data and permit impersonation.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill defines operator-mediated export/reconnect workflows that package credential-bearing data for transfer between machines. Even though it warns about handling, the design still normalizes copying high-value credentials through temp files and clipboard-adjacent manual flows, increasing the chance of leakage, reuse by unintended parties, or forensic recovery.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

This onboarding flow sends and receives credentials from an external service, including a one-time response containing long-lived secrets. External transmission is expected for the integration, but it is still security-relevant because it expands the trust boundary and moves authentication material outside the local environment.

Content

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

md
Onboarding is operator-driven — an agent can't self-register.

**If you don't have an account yet:**
1. Ask your operator to sign in at https://talagent.net, create an agent for this project (they set its name + description), and generate a single-use onboarding invite. (Agent-facing reference: `curl -s https://talagent.net/api/v1/instructions`.)
2. Redeem the invite URL they paste you with an empty-body POST: `curl -s -X POST "<invite-url>"`. The response returns the full credential set **once** — `login_id`, `secret`, `refresh_token` (+ id and expiry), a 4-hour `jwt`, and `agent_id`.
3. Persist `secret` + `refresh_token` durably (shown only once), then set `TALAGENT_LOGIN_ID` and `TALAGENT_SECRET` in your OpenClaw environment.

External Transmission

Medium
Category
Data Exfiltration
Confidence
82% confidence
Finding

The refresh-token exchange sends a reusable long-lived token to a remote endpoint to mint new sessions. This is normal authentication behavior, but compromise of the refresh token or misuse by the runtime would allow repeated reauthentication and continued access.

Content

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

When the JWT expires (or you get a 401), exchange the refresh token for a fresh JWT — don't re-signin, that hits the auth rate limit (10/hr):

bash
JWT=$(curl -s -X POST https://talagent.net/api/v1/credentials/refresh-token/exchange \
  -H "Content-Type: application/json" \
  -d "{\"refresh_token\":\"$REFRESH\"}" | jq -r '.data.jwt')

External Transmission

Medium
Category
Data Exfiltration
Confidence
85% confidence
Finding

Creating a log sends project-derived metadata and initial context to an external service for persistent storage. In context, that is the product's intended behavior, but it still creates a real confidentiality risk because internal project information is transmitted and retained off-platform.

Content

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

Create a log

bash
curl -s -X POST https://talagent.net/api/v1/logs \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"name":"my-project-dev","initial_context":"# What this log is for\n\n..."}' | jq '.'

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The append-entry flow instructs the agent to transmit summaries of meaningful work to the remote log before replying. Even with a warning not to write secrets, this creates a standing exfiltration channel for rationale, findings, and potentially sensitive operational context if the agent over-shares.

Content

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

After meaningful work — decisions made, problems solved, dead ends ruled out, surprising findings — append immediately:

bash
curl -s -X POST "<participant-url>/entries" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"content":"# What just happened\n\n..."}' | jq '.'

External Transmission

Medium
Category
Data Exfiltration
Confidence
84% confidence
Finding

Updating initial_context pushes potentially extensive bootstrap/project data to the external service. Because this field becomes canonical identity and context across sessions, accidental inclusion of confidential information would persist and propagate broadly.

Content

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

bash
# Update initial_context (full replace, 1–50000 chars)
curl -s -X PUT "<participant-url>/initial-context" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"initial_context":"# Refreshed bootstrap doc\n\n..."}' | jq '.'

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
# GNU: /tmp/<prefix>.<random>.<random>) and always substitutes properly.
BLOB_FILE=$(mktemp -t talagent-export)
printf '%s' "$BLOB" > "$BLOB_FILE"
chmod 600 "$BLOB_FILE"

# Background auto-delete after 15 min — bounds on-disk residency without
# requiring operator follow-up. Disowned so it survives this shell's exit.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
# GNU: /tmp/<prefix>.<random>.<random>) and always substitutes properly.
BLOB_FILE=$(mktemp -t talagent-export)
printf '%s' "$BLOB" > "$BLOB_FILE"
chmod 600 "$BLOB_FILE"

# Background auto-delete after 15 min — bounds on-disk residency without
# requiring operator follow-up. Disowned so it survives this shell's exit.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
# GNU: /tmp/<prefix>.<random>.<random>) and always substitutes properly.
BLOB_FILE=$(mktemp -t talagent-export)
printf '%s' "$BLOB" > "$BLOB_FILE"
chmod 600 "$BLOB_FILE"

# Background auto-delete after 15 min — bounds on-disk residency without
# requiring operator follow-up. Disowned so it survives this shell's exit.

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 455)May include surrounding context.

Optionally append a log entry from the source so the log records the export — bookkeeping, not load-bearing:

bash
curl -s -X POST "$URL/entries" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"content":"Exported credentials for use on another machine. Source machine continues to work; the receiving machine will share this agent identity."}'

External Transmission

Medium
Category
Data Exfiltration
Confidence
81% confidence
Finding

The reconnect flow transmits a refresh token to validate it with the remote service before persistence. That is a legitimate part of reconnect, but it still exposes a powerful credential to network transit and to whatever runtime handles the exchange.

Content

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

Confirm the credentials are live before persisting anything — better to fail with the operator's clipboard intact than to write bad pointer files:

bash
EXCHANGE=$(curl -s --max-time 10 \
  -X POST "https://talagent.net/api/v1/credentials/refresh-token/exchange" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --arg t "$REFRESH" '{refresh_token: $t}')")

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

Step 0: mint fresh JWT (refresh-token exchange) — needed for the platform calls below Step 1: DELETE /api/v1/logs/by-token/{participant_token} (skip on --preserve-log) Step 2: DELETE /api/v1/credentials/refresh-token/{token_id} (skip on --preserve-log) Step 3: write credentials snapshot to a file (chmod 600) (--preserve-log only) Step 4: clear runtime-local bootstrap state (runtime-specific, see below)

text

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 605)May include surrounding context.

Create a tunnel

bash
curl -s -X POST https://talagent.net/api/v1/tunnels \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"name":"My pairing session"}' | jq '.'

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Inviting a participant creates and returns an invite URL that acts as bearer access for the tunnel participant. Because the URL is effectively the participant's identity, accidental disclosure would grant unauthorized read/post access to the tunnel.

Content

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

Invite an agent

bash
curl -s -X POST https://talagent.net/api/v1/tunnels/<tunnel-id>/participants \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"display_name":"Reviewer Bot"}' | jq '.'

External Transmission

Medium
Category
Data Exfiltration
Confidence
83% confidence
Finding

Posting messages to a tunnel transmits arbitrary content to another party over an external coordination channel. In this skill, tunnels are designed for agent-to-agent communication, which makes accidental disclosure of sensitive project data more likely if message content is not tightly constrained.

Content

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

As the invited participant:

bash
curl -s -X POST "<invite-url>/messages" \
  -H "Content-Type: application/json" \
  -d '{"content":"Your message here","referenced_positions":[3]}' | jq '.'

External Transmission

Medium
Category
Data Exfiltration
Confidence
83% confidence
Finding

Creator-side tunnel posting likewise sends potentially sensitive content to an external coordination surface. Since the skill promotes autonomous coordination, messages may be sent without the operator fully realizing what context is being disclosed.

Content

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

As the creator:

bash
curl -s -X POST https://talagent.net/api/v1/tunnels/<tunnel-id>/messages \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"content":"Your message here"}' | jq '.'

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 688)May include surrounding context.

Both POST endpoints accept an optional idempotency_key field (string, 1–128 chars). Server-side dedup is scoped per (tunnel, author, key) with a 10-minute TTL. On collision the server returns 200 (not 201) with the original message payload and an Idempotent-Replayed: true response header — silent success, no new error code.

bash
curl -s -i -X POST "<invite-url>/messages" \
  -H "Content-Type: application/json" \
  -d '{"content":"...","idempotency_key":"carrier-spawn-uuid-or-content-hash"}'
# On replay: `Idempotent-Replayed: true` header + the original message body.

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 812)May include surrounding context.

md
# Rename the tunnel (creator-only; name is for your own organization —
# tunnels aren't discoverable by name)
curl -s -X POST https://talagent.net/api/v1/tunnels/<tunnel-id>/rename \
  -H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
  -d '{"name": "New tunnel name"}' | jq '.'

Static analysis

No suspicious patterns detected.