Summary
DiscordApproval accepts unrelated channel messages as dangerous-tool approvals
praisonai.bots.DiscordApproval approves a pending dangerous tool call when it
sees any later non-bot message in the configured Discord channel whose text is
classified as approval, such as yes.
The decision is not bound to:
- a Discord reply to the approval message;
- a Discord thread created for that request;
- a Discord interaction/button callback for that request;
- an explicit approver user allowlist; or
- an approval nonce visible only to intended approvers.
As a result, any user who can post in the configured approval channel can
approve a pending high-risk tool call by sending yes after the approval
message appears. The same local PoV also shows that the Slack and Telegram
messaging approval backends have no explicit approver allowlist parameter, but
the primary report-grade issue is the Discord backend's unthreaded channel
cross-talk: the approving message does not need to be a reply or otherwise
request-bound.
Affected Product
- Repository:
MervinPraison/PraisonAI - Ecosystem:
pip - Package:
praisonai - Component: Python messaging approval backends
- Primary affected file:
src/praisonai/praisonai/bots/_discord_approval.py - Related sibling files:
src/praisonai/praisonai/bots/_slack_approval.pysrc/praisonai/praisonai/bots/_telegram_approval.py
- Latest PyPI version validated:
4.6.58 - Current
origin/mainvalidated:1ad58ca02975ff1398efeda694ea2ab78f20cf3e - Current
origin/maintag validated:v4.6.58
Suggested affected range:
pip:praisonai >= 4.5.2, <= 4.6.58
Representative local sweep:
4.5.0 Discord approval backend not present
4.5.2 vulnerable
4.5.128 vulnerable
4.6.9 vulnerable
4.6.10 vulnerable
4.6.56 vulnerable
4.6.57 vulnerable
4.6.58 vulnerable
Root Cause
DiscordApproval.request_approval() posts an approval message to the configured
channel and records the returned message id.
_poll_for_response() then polls channel history with:
f"/channels/{channel_id}/messages?after={message_id}&limit=10"
For each later non-bot message, it reads content, classifies the text, and
returns ApprovalDecision(approved=True) when the text is approve/yes.
There is no check that the message is a Discord reply to the approval message,
belongs to a request-specific thread, came from an intended approver, or
contains a request-specific approval token.
Important source evidence from origin/main:
_discord_approval.pylines 57-73: constructor acceptstoken,channel_id,timeout, andpoll_interval; no approver allowlist._discord_approval.pyline 239: polls all messages after the approval
message in the configured channel._discord_approval.pylines 252-265: skips bot messages, classifies the
remaining text, and approves when the keyword isapprove.
The Slack and Telegram backends are better request-scoped than Discord:
- Slack uses
conversations.repliesfor the approval message thread. - Telegram checks the callback/reply message id.
However, both still lack an explicit approver identity parameter. They are
included in the PoV and suggested fix because the authorization model should be
consistent across all messaging approval backends.
Local PoV
Run against the latest local checkout:
python3 poc/pov_prai_cand_029_messaging_approval_channel_member_bypass.py \
--repo ../../artifacts/repos/praisonai-v4.6.58 \
--json
The PoV is local-only. It mocks Slack, Telegram, and Discord API helpers
in-process and does not contact those services.
For Discord, the mock sequence is:
DiscordApprovalposts a criticalexecute_commandapproval request toD_APPROVAL_CHANNEL.- The mocked channel-history endpoint returns a later ordinary non-bot
channel message fromD_INTRUDERwith contentyes. DiscordApprovalreturnsapproved=Trueandapprover="D_INTRUDER".
Observed output from evidence/pov-v4.6.58.json:
{
"approval_from_unconfigured_channel_participant": {
"discord": true,
"slack": true,
"telegram": true
},
"backends": [
{
"backend": "discord",
"configured_channel_id": "D_APPROVAL_CHANNEL",
"decision_approved": true,
"decision_approver": "D_INTRUDER",
"decision_reason": "Approved via Discord by intruder",
"intruder_user": "D_INTRUDER"
}
],
"no_explicit_approver_allowlist_parameters": true,
"vulnerable": true
}
The command in the approval request is a harmless local sentinel:touch /tmp/prai-cand-029. The PoV stops at the approval decision; it does not
execute the tool.
Why This Is Not Intended Behavior
This report does not claim that a deliberately private approval channel with
only trusted approvers is unsafe by itself. The narrower issue is that the
Discord backend treats an unrelated later channel message as the approval
decision for a specific dangerous tool request.
PraisonAI's approval documentation describes approval as a safety control that
pauses before dangerous tools and asks a human or channel to allow or deny the
specific request. A random later yes in the channel is not evidence that an
intended approver reviewed that request.
The existing Slack and Telegram implementations already show request-binding
patterns that Discord lacks:
- Slack scopes to replies for the approval message timestamp.
- Telegram checks the callback/reply
message_id.
The Discord backend should provide at least the same request binding and should
also support explicit approver identity checks for deployments where channel
membership is broader than approval authority.
Severity
Suggested severity: High.
Rationale:
AV: the attacker interacts through a networked Discord channel.AC: sendingyesafter an approval prompt is enough.PR: the attacker needs permission to post in the configured approval
channel, but no approver-specific permission.UI: no separate victim interaction is needed after the prompt exists.S: the vulnerable approval backend and approved tool run in the PraisonAI
application's security scope.C/I/A: approved dangerous tools can disclose, modify, or destroy data
depending on the configured agent tools.
Impact
If an application uses DiscordApproval for dangerous tools such as shell
commands, file writes, deletes, deployments, or other privileged operations, a
low-privileged Discord user with write access to the configured approval channel
can approve pending dangerous tool executions.
This can lead to code execution, file modification, deployment changes, or data
access with the privileges of the PraisonAI process, depending on which tools
the agent exposes behind approval.
The attacker does not need the LLM API key, shell access, repository access, or
PraisonAI process access. They only need to be able to post an approval-looking
message in the configured approval channel after the approval prompt appears.
The application does not correctly enforce access controls, allowing a principal to access resources or operations beyond their granted permissions. Typical impact: unauthorized data access or execution of privileged operations.
GHSA-8579-RGG5-PH2M has a CVSS score of 8.8 (High). The vector is network-reachable, low privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (4.6.59); upgrading removes the vulnerable code path.
Affected versions
Security releases
Kodem intelligence
Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.
Remediation advice
Recommended fixes:
- For Discord, require approvals to be tied to the request, not merely any
later channel message. Use Discord interactions/buttons with opaque
server-side request ids, or require a Discord reply whosemessage_reference.message_idmatches the approval message. - Add explicit approver identity configuration to all messaging approval
backends, for exampleapprover_user_idsorallowed_approvers. - Reject approvals from users outside the configured approver set, even if the
message appears in the configured channel. - Include a per-request nonce or opaque approval id in callbacks and verify it
server side before returningApprovalDecision(approved=True). - Add regression tests for Discord where:
- an unrelated later
yesin the channel is ignored; - a reply from a non-approver is ignored;
- a request-bound reply/callback from an allowed approver succeeds.
- an unrelated later
Frequently Asked Questions
- What is GHSA-8579-RGG5-PH2M? GHSA-8579-RGG5-PH2M is a high-severity incorrect authorization vulnerability in praisonai (pip), affecting versions >= 4.5.2, <= 4.6.58. It is fixed in 4.6.59. The application does not correctly enforce access controls, allowing a principal to access resources or operations beyond their granted permissions.
- How severe is GHSA-8579-RGG5-PH2M? GHSA-8579-RGG5-PH2M has a CVSS score of 8.8 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
- Which versions of praisonai are affected by GHSA-8579-RGG5-PH2M? praisonai (pip) versions >= 4.5.2, <= 4.6.58 is affected.
- Is there a fix for GHSA-8579-RGG5-PH2M? Yes. GHSA-8579-RGG5-PH2M is fixed in 4.6.59. Upgrade to this version or later.
- Is GHSA-8579-RGG5-PH2M exploitable, and should I be worried? Whether GHSA-8579-RGG5-PH2M is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
- What actually determines whether GHSA-8579-RGG5-PH2M is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
- How do I fix GHSA-8579-RGG5-PH2M? Upgrade
praisonaito 4.6.59 or later.