T09 · Insecure Skill Coding Practices
- Location
scripts/collect/recorders/turns.ts:24- Finding
Untrusted call transcripts are processed by a credential-bearing repository-write agent
- Content
View full analysis
Vulnerability Details
File Location:
scripts/collect/recorders/turns.ts:24-38;scripts/collect/recorder.ts:362-389;infra/agents/call-scribe.prompt.ts:31-36,64-105;infra/agents/call-scribe.ts:27-31,43-52
Vulnerability Type: Indirect prompt injection across an external-content trust boundary
Risk Level: HighVulnerable Code
scripts/collect/recorders/turns.ts:24-38preserves recorder-supplied speaker names and transcript text as Markdown without identifying or isolating them as untrusted instructions:ts export function renderTurns(turns: Turn[]): string | null { const merged: { speaker: string; parts: string[] }[] = []; for (const turn of turns) { const text = turn.text.trim(); if (text === "") continue; const speaker = turn.speaker !== undefined && turn.speaker.trim() !== "" ? turn.speaker.trim() : "Speaker"; const last = merged[merged.length - 1]; if (last !== undefined && last.speaker === speaker) last.parts.push(text); else merged.push({ speaker, parts: [text] }); } if (merged.length === 0) return null; return merged .map((turn) => `**${turn.speaker}:** ${turn.parts.join(" ")}`) .join("\n\n"); }scripts/collect/recorder.ts:362-389writes that external content directly into a raw Markdown file:ts const frontmatter = [ "---", `title: "RAW: ${call.subject.replace(/"/g, "'")}"`, `date: ${day}`, `attendees: [${attendees}]`, // The written half of the idempotency key. Its reader is capturedIds(), // and both are built from `provider` so they cannot disagree. `source: ${provider} ${call.id}`, "status: raw, awaiting scribe", "---", "", ].join("\n"); writeFileSync(path, `${frontmatter}\n${body}\n`); return relative(ROOT, path); }infra/agents/call-scribe.prompt.ts:31-36,64-105instructs the scheduled agent to read repository instructions and process each raw capture, but it does not establish that tr ...[truncated 5792 chars]- Remediation
View remediation
Remediation Suggestions
-
Explicitly classify recorder content as untrusted data.
- Add a high-priority instruction stating that transcript text, speaker names, subjects, notes, and embedded Markdown are data only.
- State that commands, tool requests, repository instructions, links, or requests for secrets appearing in those fields must never be followed.
-
Separate collection credentials from the LLM process.
- Run the deterministic collector in an isolated process with access only to
CALL_RECORDER_API_KEY. - Remove recorder credentials and unrelated workspace variables from the environment before starting the Claude Code harness.
- Use an explicit environment-variable allowlist rather than inheriting the entire workspace catalog.
- Run the deterministic collector in an isolated process with access only to
-
Constrain the agent’s filesystem and Git permissions.
- Permit writes only under the expected raw, call-log, and context directories.
- Deny changes to infrastructure, agent prompts, executable scripts, configuration files, and CI definitions through technical policy rather than prompt text alone.
- Use a token restricted to creating branches and pull requests only for the bound repository.
-
Restrict runtime capabilities.
- Disable arbitrary outbound network access during transcript processing.
- Prevent shell commands from reading environment variables or unrelated files.
- Replace the general coding harness with a constrained transformation worker where feasible.
-
Use structured input and output boundaries.
- Pass transcripts as typed data fields or escaped blocks clearly delimited from instructions.
- Require generated output to conform to a schema containing only the approved log and context fields.
- Treat Markdown control syntax in speaker names, subjects, and transcript text as literal content.
-
Add a mandatory pre-push security gate.
- Scan staged changes and pull-request text for workspace secrets, credential patterns, unexpected files, ex ...[truncated 577 chars]
-
