P.K. SHARMA

Cyber security intelligence, AI governance, practitioner analysis

Agentforce could post to Slack with no confirmation and no attribution, and both were the defaults

Zenity Labs found that the Reply to a Slack Thread action in Agentforce's default Slack Knowledge subagent sent messages without asking the user and without recording who triggered it. A poisoned lead was enough to use it.

By Parminder Kumar Sharma · · 8 min read

Editorial illustration for the briefing: Agentforce could post to Slack with no confirmation and no attribution, and both were the defaults

Two controls that were never there

Zenity Labs reported a flaw in Salesforce Agentforce on 1 June 2026. The last fix landed on 21 September, 112 days later. Between those dates the interesting thing is not how long it took, but what was actually wrong.

Nothing was broken. The Reply to a Slack Thread action, in the default Slack Knowledge subagent template, simply did not have two things: a step where the user approves the message before it goes, and a record of which user's request caused it. In Zenity's words, "the missing confirmation step meant that once Agentforce decided to invoke Reply to a Slack Thread, the message could be sent without the user approving it".

So a message could arrive in a Slack channel, written by an agent, at the instruction of somebody nobody could identify.

What that does not establish. It does not establish that anyone was attacked: Zenity describes research, not an incident, and no victim is named. It does not establish a flaw in the underlying model, because the model behaved as models do when instructions arrive inside data. It does not establish that Salesforce was slow in any general sense, since the URL side of the research was fixed in 79 days and attribution in 80. And it does not establish anything about other agent platforms, except by analogy, which is where most of the value is.

What it does establish is that an action capable of speaking to your colleagues shipped, by default, without the two controls that make a message traceable.

How a lead becomes a message

Web-to-Lead is an ordinary Salesforce feature. It turns a form on your website into a record in your CRM, which is the entire point: strangers put data into your systems, on purpose, all day.

The attack uses that. An external attacker submits a lead that looks normal and carries hidden instructions in one of its fields. Later, an internal user asks the agent to help with that lead. The agent reads the record, treats the embedded instructions as instructions, and executes them instead of the user's actual request. Zenity's own framing is that an attacker "could place malicious instructions in data submitted to an organization's CRM (such as in a lead submitted through a Web-to-Lead form, which is used by many companies)".

What the instructions ask for is a Slack message, and this is where the missing controls matter. The agent sends it without asking. The message appears under the agent's identity. Nobody can see whose request produced it.

There is a second, simpler version that needs no injection at all. An authorised user tells the agent directly to post phishing links into Slack threads. Same outcome, no attribution, and the user's own name never appears.

A diagram of two routes to the same unattributed Slack message. On one, an outsider submits a poisoned Web-to-Lead form and an internal user later asks the agent about that lead, so the agent executes the hidden instructions. On the other, an authorised insider asks the agent directly. Both reach the Reply to a Slack Thread action, drawn with two missing gates: no confirmation before sending, and no record of who triggered it.
Drawn from the Zenity Labs disclosure of September 2026.

What each missing control actually cost

The two controls, what they would have prevented, and what Salesforce did

Missing controlWhat it allowsThe fix
User confirmation before sendingThe agent acts on instructions the user never saw, including instructions that arrived inside dataConfirmation added as the default behaviour for the action
Attribution of the invoking userA message under the agent's identity with no record of whose request produced itAttribution added so the invoking user is identified
URL redaction that matched the rendererA crafted untrusted link surviving redaction and rendering as a working linkRedaction updated to close the bypass

Read the first row as a design principle rather than a bug report. An agent that can take an action on your behalf has to distinguish between what you asked for and what it read. Confirmation is the crude, effective way of doing that: it puts a human between the instruction, wherever it came from, and the effect.

The second row is the one people skip. Attribution is not a security control against the attacker; it is a control against everyone else's uncertainty afterwards. Without it, an organisation that finds a phishing link posted by its own agent cannot answer the first question an investigation asks, which is who asked for this.

The third row is the other half of the same research. Agentforce uses a Trusted URLs allow list to stop agents producing links to places they should not. Zenity found that, as The Register and others reported, certain top level domains and URL ending characters were handled differently by the redactor and by the surface that consumed its output, so a crafted untrusted URL could pass through unrecognised. This briefing takes the phishing chain from the primary research and treats the URL and exfiltration detail as reported, because the full technical write up of that half sits in Zenity's earlier post.

The timeline, and what it shows about fixing defaults

Zenity's disclosure timeline, with elapsed days computed for this briefing

DateStepDays from report
1 June 2026Reported to Salesforcezero
2 June 2026Salesforce confirms and begins work1
17 June 2026Engineering actively developing a fix16
19 August 2026Trusted URLs bypass fix confirmed by Zenity79
20 August 2026Attribution added to the Slack action80
25 August 2026User confirmation fix still in progress85
10 September 2026Confirmation fix expected by 21 September101
21 September 2026All fixes confirmed and tested112

The shape of that list is worth noticing. The two changes that look like bugs, a redaction bypass and a missing attribution field, were done inside eighty days. The change that alters what the product does by default, making the agent ask before it speaks, took a further month.

That is not a criticism. Changing a default changes behaviour for every customer who did not ask for the change, including customers whose workflows depend on the agent not stopping to ask. It is slower because it is riskier, and the fact that it is riskier is precisely why shipping the permissive version first was the wrong way round.

The general case, which is not about Salesforce

Strip the product names out and this is a description of almost every agent platform currently being sold.

An agent is given a set of actions. Some of those actions are reads and some are sends. A send is any action whose effect leaves the system and reaches a person: a Slack message, an email, a calendar invite, a ticket comment, a webhook into somebody else's tool. The security properties that matter for a send are not the same as for a read, and most platforms are still configured as though they were.

Two questions cover most of it. Before this action takes effect, does a human see what it will do? After it has taken effect, can anyone tell whose request caused it?

When the answer to both is no, and the agent also reads data that strangers can write into, the platform has an unattributed send primitive that anybody on the internet can aim.

What to do about it

Take this with you

In the order worth doing

  • If you run Agentforce with the Slack integration, confirm you are on the fixed behaviour and that confirmation is enabled rather than switched off in a template somebody copied earlier.
  • Inventory every agent action in your estate and split it into reads and sends, because the two need different controls.
  • Require human confirmation on every send, and treat any exception as a documented risk acceptance with a named owner.
  • Require invoker attribution on every send, so that an investigation can start with who rather than what.
  • Identify every source of agent readable data that an outsider can write to: web forms, inbound email, support tickets, public documents, shared drives.
  • Test your own agents with an instruction embedded in one of those fields, in a sandbox, and see whether the action fires.
  • Keep the allow list and the renderer honest: if one component decides what is a valid URL and a different component fetches it, get somebody to check they agree.

The question this leaves

Salesforce comes out of this reasonably well. It confirmed the report the next day, fixed the two mechanical problems inside eighty days, and changed a default even though changing defaults is the expensive option. Zenity disclosed it properly and published the timeline, including the awkward month in the middle.

The uncomfortable part is what the default was in the first place. Somebody built a template in which an agent could speak in a shared channel, on behalf of a user, without that user seeing the message and without their name attached to it. Not as a configuration mistake. As the shipped starting point that customers were expected to copy.

Every agent platform has a set of those starting points, and most organisations adopt them unchanged because that is what a template is for. So the question is not whether your agent can be tricked by a poisoned record. It is: which of the actions your agents can take today were chosen by you, and which arrived in a template you accepted?

Sources

  1. PrimaryThe primary research for the Slack chain, the two missing controls and the full disclosure timelineZenity Labsaccessed 2026-09-25
  2. PrimarySalesforce's own documentation for Web-to-Lead, used for what the injection vector is in normal useSalesforceaccessed 2026-09-25
  3. Reported bySecondary coverage, used only for the data exfiltration half of SalesBleed, which this briefing labels as reported rather than verified hereThe Registeraccessed 2026-09-25

Share this briefing

Know someone who owns this problem? Send it to them.

Related briefings

The briefing, in your inbox

Practitioner analysis of cyber and AI security news. No vendor noise.

One email per briefing. Unsubscribe any time.