Breachwire.riscent

Breach report

Slack AI: hidden text in a public channel that stole secrets from private ones

AI & LLM BreachesHigh2024-08
The bottom lineAn attacker who could post to a public Slack channel could plant hidden instructions that made Slack AI leak secrets from private channels the attacker could not access.
Category
AI & LLM Breaches
Type
Named incident (Slack AI / PromptArmor)
Date
2024-08
Severity
High
OWASP
LLM01 Prompt Injection; LLM08 Vector & Embedding Weaknesses
CWE / CVE
CWE-77

What happened

Slack AI answers questions by drawing on the messages a user can see across their workspace. PromptArmor disclosed an indirect prompt injection, reported to Slack in August 2024, in which content an attacker placed in a public channel could exfiltrate data from private channels the attacker had no access to.

The attacker created a public channel and posted malicious instructions disguised as ordinary content. When a victim later queried Slack AI, the system processed the victim's question together with the attacker's planted text. Because the model could not distinguish legitimate context from injected instructions, it followed the attacker's commands. The payload told Slack AI to embed sensitive data — for example an API key sitting in a private channel — inside a Markdown link with enticing text such as "click here to reauthenticate." When the victim clicked, their secret was transmitted to the attacker's server as a URL parameter. The exfiltration stayed hidden partly because Slack AI did not cite the malicious source. PromptArmor also noted that once Slack AI began ingesting uploaded files and documents, an attacker could hide the same instructions in a PDF using techniques like white text, widening the attack surface. Slack initially characterized public-channel access as intended behavior.

Root cause

  • LLM01 Prompt Injection (indirect). Slack AI merged untrusted channel content with the user's query and treated planted text as instruction — the classic trust-boundary failure.
  • LLM08 Vector & Embedding Weaknesses. The retrieval layer pulled attacker-authored content from a public channel into a context that also contained private-channel secrets, crossing a tenant/permission boundary the user never intended.

How it would have been caught

A retrieval-injection probe — placing a hidden-instruction message into an indexable public channel and asking a benign question while watching for outbound requests — would have surfaced the behavior. Promptfoo, Garak, and PyRIT automate this class of test. An output check that blocks or de-links model-authored URLs to non-allowlisted hosts closes the click-to-exfiltrate channel.

How to prevent it

  • Deliver retrieved messages and files as labelled, source-tagged untrusted data, not as instructions, and always cite sources so injected content is attributable.
  • Strip or neutralize model-generated links to non-allowlisted domains so a stolen secret cannot ride out in a URL.
  • Keep the retrieval boundary aligned with intent — do not blend attacker-writable public content with private-channel secrets in one context without provenance.

The Breachwire test (red → green)

Plant a hidden-instruction message in a public channel, query Slack AI as the victim, and confirm a private-channel secret exfiltrates via a crafted link (the RED control proving the vector). Apply link-stripping and source citation, then confirm the same payload no longer leaks, while a benign cross-channel question still returns a correct, cited answer (the positive control).