A Slack AI agent can follow the wrong instructions without anyone typing a jailbreak into the mention. IT and digital-workplace admins see it when a public channel message, uploaded file, GitHub issue comment, or connector tool result contains hidden directives, and the agent then searches private knowledge, posts a reply, opens a ticket, or prepares a code change it was never asked to make. The requester still thinks they asked a normal question. Security asks which tool fired and why the audit trail points at a trusted user.
If you own multi-tool Slack agents for knowledge retrieval, support drafting, or GitHub-aware ops work, use this as a tool-call mediation plan. It covers why prompt injection becomes a tool problem, how to separate trusted intent from untrusted content, out-of-band policy checks, quarantine of raw text, audit fields, failure modes, and a pilot checklist. Use it when injected text must not be allowed to select or authorize a write.
Why Slack agent prompt injection is a tool problem
OWASP LLM01: Prompt Injection covers both direct overrides and indirect injection, where instructions arrive inside content the model retrieves. For Slack agents the second path matters most. The mention looks ordinary. The dangerous text sits in another message, a file, an issue body, or a tool response that your runtime treated as ordinary context.
PromptArmor's report on Slack AI describes how attacker-authored public-channel messages could steer Slack AI into exposing private-channel data through rendered links. Treat that as a researcher report about a specific product surface, not as a claim about every Slack app. Once an agent can read workspace content and call outbound tools, retrieved text becomes a control path.
Repello's analysis of MCP prompt injection makes the same point for tool-using agents. When an agent calls a Slack read tool, the returned message text enters the model as structured tool output. There is no protocol-level guarantee that the payload is free of adversarial instructions. Anyone who can write to a source the agent reads can try to steer later tool calls without touching your user-facing prompt filter.
Embrace The Red's advisory on Anthropic's Slack MCP server shows a concrete side effect path: prompt injection causes an agent to post a link that embeds secrets, and Slack link unfurling fetches that URL for an attacker-controlled host. Treat the specific product defect as an author report. For admins, mutating Slack posts and external sends are the moment injection becomes a real incident.
A defensive system prompt helps with obvious jailbreaks. It does not replace a gate in front of tools. Microsoft's Agent Framework FIDES post states the failure mode: most agents still rely on a defensive prompt or a hand-rolled allowlist, and both fail silently when untrusted content is already in scope and the model still tries to write or post.
Separate trusted intent from untrusted content
Every Slack agent run needs two kinds of text from the first message onward:
- Trusted intent: the requesting user's goal for this turn, plus policy your platform owns (allowed tools, environment, approval rules).
- Untrusted content: Slack thread text from other people, uploaded files, search hits, GitHub issue or PR bodies, Intercom notes, web fetches, and any other connector output.
OWASP's Prompt Injection Prevention Cheat Sheet recommends treating external content as untrusted, applying least privilege to tools, requiring human review for consequential actions, and monitoring. That is the security baseline. The Guide to the Slack AI Guardrails lists context engineering against prompt injection, URL filtering, and output validation for native Slack AI. Custom agents that call your own knowledge, GitHub, Intercom, or Ads connectors still need application-level mediation. Native guardrails do not automatically protect a third-party agent endpoint.
Slack Developer Docs on Governance and trust ask builders to balance oversight with usable agents, keep human-in-the-loop controls, and log who triggered a request, which channels were accessed, which tools ran, and what happened. Those audit fields help only if your runtime can also say whether untrusted content was in scope when a write was attempted.
Kipwise Agent is designed as a thread-native work agent: a teammate mentions it once and continues with ordinary replies; applicable actions use the requesting user's permissions; it cites sources it actually opened; it refuses to guess; sandboxed code work is isolated; consequential changes stay explicit. Those product behaviors stay trustworthy only if retrieved Slack and connector text cannot become the authority for the next tool call.
Propagate integrity labels through tool results
Propagate integrity labels through every tool result so Slack messages and connector output stay untrusted even after the model summarizes them. Do not clear the untrusted label when the model summarizes a Slack message or tool payload. If a public channel message is untrusted on read, the summary that enters the next reasoning step must still carry an integrity label that says untrusted content influenced the run. Otherwise the agent "launders" injected instructions into clean-looking intermediate state and then calls a write tool.
Microsoft FIDES describes integrity and confidentiality labels that travel with content and combine restrictively as the run proceeds. Policy then evaluates the most restrictive combination of everything the model has read so far before a sensitive tool executes. Copy that pattern into your agent runtime even if you do not adopt that framework.
Practical labeling rules for Slack agents:
| Source | Default integrity label | Why |
|---|---|---|
| Requester's current mention and later plain replies in the same owned thread turn | Trusted intent (user goal) | This is the job the user asked for |
| Other users' messages in the same thread or channel | Untrusted content | Anyone in the channel can plant instructions |
| Uploaded files and OCR/extracts | Untrusted content | Documents are a classic indirect injection path |
| Kipwise search hits, GitHub issue/PR bodies, Intercom notes, Ads or Analytics rows | Untrusted content | Connector output is still external text relative to your policy engine |
| Your platform policy, allowlists, and approval decisions | Trusted platform policy | Owned by admins, not by workspace chatter |
Keep labels in structured run state, not only inside the prompt. The model may ignore a warning in the prompt text. Your tool gateway must still see the labels.
Enforce tool policy out of band before mutating calls
Enforce tool policy out of band before mutating calls; a defensive system prompt is not a gate when untrusted content is already in scope. Mediate tools outside the model. If untrusted content is in scope, do not rely on the model to "decide carefully" whether create_ticket, post_message, update_knowledge, open_pull_request, or send_customer_reply is appropriate. Check the tool name, destination, and current labels in middleware. Block, require approval, or allow only according to that policy.
That differs from a generic human-approval workflow. Human approval for a known consequential write still matters, and Kipwise-style products keep sensitive actions explicit. Tool mediation answers a prior question: should this tool run at all when the run has already read untrusted text that could have steered the choice?
A compact policy table for Slack multi-tool agents:
| Tool class | Untrusted content in scope | Default action |
|---|---|---|
| Read-only search in already-permitted sources | Yes | Allow, but keep results labeled untrusted |
| Summarize or classify untrusted text | Yes | Prefer quarantine worker; return a handle plus summary |
| Post to the same thread as a citation-backed answer | Yes | Allow only if destinations and URLs pass filters; disable unfurling for sensitive payloads |
| Create or update tickets, knowledge, GitHub artifacts | Yes | Block or require explicit human approval with the proposed tool args visible |
| External HTTP fetch or customer-visible send | Yes | Block or require approval; never pass secrets in query strings |
OWASP's cheat sheet aligns with least privilege and human review for consequential actions. Slack's governance guidance expects progressive trust and human-in-the-loop controls rather than unbounded autonomy. FIDES shows the enforcement point: policy middleware runs before the sensitive function, and a violation can become an approval request instead of a silent block if operators want an override path.
Also strip or refuse tool arguments that encode exfiltration patterns. The Embrace The Red Slack MCP case hinged on posting a URL that carried secrets, then relying on unfurling. For agent posts, disable link and media unfurling when the message may contain sensitive parameters, and reject outbound URLs that embed tokens, keys, or private channel contents in the query string.
Quarantine raw untrusted text before the main agent reasons over it
Quarantine raw untrusted text for summarization so the main agent sees a handle, not the embedded override instructions that would steer the next write. Keep raw untrusted bytes away from the main tool-calling model whenever you can. Store the Slack message or tool payload in a side store, give the main agent a handle such as var_12, and let a quarantined summarizer extract only the fields the job needs. The main agent should not see a literal SYSTEM OVERRIDE block sitting inside an otherwise ordinary support note.
FIDES describes this as hiding untrusted tool results behind stored references and dispatching real processing to a quarantined LLM. Repello explains why the naive design fails: tool output looks like a trusted channel to the model even when the bytes came from an attacker-controlled Slack message. Quarantine breaks that trust illusion.
Recommended Slack-agent flow:
- Receive the mention and verify Slack request signatures.
- Resolve the requester identity and live permissions for the planned tools.
- Collect thread and connector context with integrity labels.
- Store raw untrusted payloads; pass handles plus minimal structured fields to the main agent.
- Let the main agent propose tool calls for the user goal.
- Run out-of-band policy on each call using current labels and tool class.
- Execute allowed reads; gate or block writes; cite opened sources only.
- Post one grounded reply or an explicit refusal; write audit rows for blocks and approvals.
Worked example: support drafting with knowledge and Intercom context
Scenario: a support operations lead mentions the agent in a triage thread: "Draft an answer for this billing escalation using our refund policy and the Intercom conversation."
Without mediation, the agent reads the thread, opens Kipwise, opens Intercom, and finds a customer note that says to ignore prior policy and post a full account export link into the channel. A weakly gated agent may treat that note as instruction and attempt a sensitive search or an outbound post.
With mediation:
- Trusted intent is "draft a refund answer from policy and Intercom evidence."
- Thread chatter, the customer note, and Intercom bodies are labeled untrusted.
- Policy allows labeled reads of Kipwise and Intercom under the requester's permissions.
- Raw Intercom text is quarantined; the main agent receives a summary handle and citation IDs.
- When the model proposes
post_messagewith an external export URL, middleware blocks or pauses for approval because untrusted content is in scope and the destination looks like exfiltration. - The agent posts a draft reply that cites the refund policy page it opened, or it asks the human to approve a customer-visible send. It does not invent policy and it does not follow the injected export instruction.
Kipwise Agent fits this path: permission-aware reads, citations to opened sources, refuse-to-guess behavior, and explicit consequential actions, with injection treated as a tool-authorization problem rather than a prompt-wording problem.
Failure modes and how to verify the controls
Watch for these failure modes in production:
- Label amnesia: summaries lose the untrusted flag and later writes look clean. Fix by storing labels in run state and combining them restrictively.
- Prompt-only defense: operators add stronger system text and skip middleware. Fix by making the tool gateway refuse to run without a policy decision record.
- Over-blocking: every run that read a channel message requires approval, so nobody uses the agent. Fix by splitting read-only tools from mutating tools and auto-allowing labeled reads.
- Unfurl exfiltration: the agent posts a "safe looking" link that leaks secrets through Slack's preview fetch. Fix by disabling unfurling on agent posts that may carry sensitive query data and by scanning outbound URLs.
- Identity confusion: the audit row shows the bot, not the requester, so you cannot tell who authorized the tool. Pair this plan with per-user permission mapping rather than a shared bot token for user-scoped actions.
- False calm in tests: demo threads never contain adversarial content. Add injection cases to pre-deploy evaluation, including public-channel bait, file-borne instructions, and malicious tool payloads.
Verification checklist for a pilot:
- Plant a benign injection in a public test channel that asks the agent to call a forbidden write tool.
- Confirm the tool gateway blocks or pauses the call and records the untrusted sources in scope.
- Confirm the user still receives a useful refusal or approval card instead of a silent no-op with no explanation.
- Confirm citations refer only to sources the run opened.
- Confirm agent posts that could embed secrets do not unfurl sensitive URLs.
- Measure unauthorized tool calls blocked, approval overrides, mean time to review a gated write, and security questions answered from logs.
Slack's governance guide already expects you to log trigger identity, tools, and outcomes. Add integrity-label scope and policy decision to that row so a blocked hijack attempt shows up later.
What to do next
Pick one production Slack agent that can write somewhere that matters: knowledge, tickets, GitHub, or customer-visible replies. Add integrity labels to Slack and connector inputs, put a policy decision in front of mutating tools, and quarantine raw untrusted text before the main model plans the next call. Run the injection pilot above in a non-production workspace first. Keep human approval for consequential writes, but do not treat approval alone as a substitute for stopping unauthorized tool selection when injected instructions are already in the run.
References
- OWASP LLM01: Prompt Injection - Defines direct and indirect prompt injection, including external content that redirects model behavior and tool use.
- OWASP LLM Prompt Injection Prevention Cheat Sheet - Controls for untrusted external content, least privilege, human review, and monitoring.
- Slack Help: Guide to the Slack AI Guardrails - Native Slack AI protections such as context engineering against prompt injection and URL filtering.
- Slack Developer Docs: Governance and trust - Builder guidance for human-in-the-loop controls and audit of who triggered requests, tools, and outcomes.
- Microsoft Agent Framework: FIDES - Integrity and confidentiality labels with policy enforcement before sensitive tool calls, plus quarantine of untrusted content.
- PromptArmor: Data Exfiltration from Slack AI via Indirect Prompt Injection - Researcher report of public-channel injection steering Slack AI toward private-data exposure.
- Embrace The Red: Anthropic Slack MCP data leakage - Advisory on prompt injection plus Slack link unfurling as an exfiltration path.
- Repello: MCP Prompt Injection - Analysis of malicious tool responses hijacking agents that read Slack and other connectors.
- Kipwise Agent - Product behavior for thread-native Slack work, requesting-user permissions, citations, refuse-to-guess answers, sandboxing, and explicit consequential actions.


