GHSA-8579-rgg5-ph2m CVE-2026-56832 PYSEC-2026-3506
PraisonAI DiscordApproval accepts unrelated channel messages as dangerous-tool approvals
- Severity
- 8.8 / 10
- High · CVSS 3.1
- Exploit chance (EPSS)
- 0.15%
- Chance of exploitation in the next 30 days. Higher than 3.96% of scored vulnerabilities.
- Known exploited
- No
- Not in CISA's catalog
- Fix
4.6.59- Upgrade praisonai to this version or later
Description
DiscordApproval accepts unrelated channel messages as dangerous-tool approvals
Summary
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 from
D_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.
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.
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.
Remediation
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 whose
message_reference.message_idmatches the approval message. - Add explicit approver identity configuration to all messaging approval
backends, for example
approver_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 returning
ApprovalDecision(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
Affected versions
PyPI
| Package | Vulnerable | Fixed in |
|---|---|---|
| praisonai | >= 4.5.2, < 4.6.59 |
4.6.59 |
How to fix
Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.
praisonai PyPI → 4.6.59
- pip
pip install --upgrade "praisonai>=4.6.59"- poetry
poetry add "praisonai>=4.6.59"- uv
uv add "praisonai>=4.6.59"
Severity breakdown
CVSS 3.1 8.8
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Attack vector
- Network
- Attack complexity
- Low
- Privileges required
- Low
- User interaction
- None
- Scope
- Unchanged
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Weakness
CWE-345: Insufficient Verification of Data Authenticity
The product does not sufficiently verify the origin or authenticity of data, in a way that causes it to accept invalid data.
CWE-863: Incorrect Authorization
The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check.
How to prevent it
- Architecture and Design: Divide the product into anonymous, normal, privileged, and administrative areas. Reduce the attack surface by carefully mapping roles with data and functionality. Use role-based access control (RBAC) [REF-229] to enforce the roles at the appropriate boundaries. Note that this approach may not protect against horizontal authorization, i.e., it will not protect a user from attacking others with the same role.
- Architecture and Design: Ensure that access control checks are performed related to the business logic. These checks may be different than the access control checks that are applied to more generic resources such as files, connections, processes, memory, and database records. For example, a database may restrict access for medical records to a specific database user, but each record might only be intended to be accessible to the patient and the patient's doctor [REF-7].
- Architecture and Design: Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid. For example, consider using authorization frameworks such as the JAAS Authorization Framework [REF-233] and the OWASP ESAPI Access Control feature [REF-45].
- Architecture and Design: For web applications, make sure that the access control mechanism is enforced correctly at the server side on every page. Users should not be able to access any unauthorized functionality or information by simply requesting direct access to that page. One way to do this is to ensure that all pages containing sensitive information are not cached, and that all such pages restrict access to requests that are accompanied by an active and authenticated session token associated with a user who has the required permissions to access that page.
- System Configuration, Installation: Use the access control capabilities of your operating system and server environment and define your access control lists accordingly. Use a "default deny" policy when defining these ACLs.
References
Advisories
Packages
Other links
Timeline
- Published
- Last updated by the source
- Latest EPSS score
Related advisories
| Advisory | Severity | Why it's related |
|---|---|---|
| GHSA-26mh-57q7-jfvr PraisonAI vulnerable to Remote Code Execution via Broken AST Sandbox | High | Also affects praisonai |
| GHSA-6g6r-q6gw-w8fg PraisonAI has a Browser Server WebSocket origin validation bypass via unanchored regex (patch bypass of CVE-2026-40289 / GHSA-8x8f-54wf-vv92) | Critical | Also affects praisonai |
| GHSA-pvph-5j39-v8qc PraisonAI: Origin-validation bypass (startswith prefix match) enables unauthenticated cross-site request forgery against the PraisonAI MCP HTTP server | High | Also affects praisonai |
| GHSA-gfq8-hmph-9gjv PraisonAI: Authentication fail-open in Recipe server allows unauthenticated access when API key or JWT auth is configured without a secret | High | Also affects praisonai |
| GHSA-2jgc-f764-c5r2 PraisonAI: [Auth Bypass] PraisonAI async Jobs API (`/api/v1/runs`) has no authentication — unauthenticated job execution, result theft, cancel and delete | High | Also affects praisonai |
| GHSA-pvxx-r596-f5qj PraisonAI: `--api-key` flag on `praisonai serve` is not properly enforced | High | Also affects praisonai |
| GHSA-hmfx-4v44-9qw9 PraisonAI vulnerable to Server-Side Request Forgery via DNS rebinding bypass in webhook_url validation | Medium | Also affects praisonai |
| GHSA-rg5q-pp8p-f7jm PraisonAI: Webhook SSRF via DNS fail-open in `JobSubmitRequest.validate_webhook_url()` — bypass of CVE-2026-40114 | High | Also affects praisonai |
MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.
Check your repos with MergeHarbor