Blog

  • Cloudflare Images – Manage hosted images with the Images binding

    Use the Images binding to upload, list, retrieve, update, and delete images stored in Images directly from your Worker without managing API tokens or making HTTP requests.

    The env.IMAGES.hosted namespace supports the following storage and management operations:

    For example, you can upload an image from a request body and return its metadata:

    const image = await env.IMAGES.hosted.upload(request.body, {
    filename: "upload.jpg",
    metadata: { source: "worker" },
    });
    return Response.json(image);

    Or retrieve and serve the original bytes of a hosted image:

    const bytes = await env.IMAGES.hosted.image("IMAGE_ID").bytes();
    return new Response(bytes);

    For more information, refer to the Images binding.

  • DNS – Account-level DNS records quota

    Cloudflare now enforces DNS records quotas at the account level for Enterprise accounts. Instead of a per-zone limit, these accounts have a quota on the total number of records across all of their zones, letting you distribute records across your zones however you like — regardless of each zone’s plan. Public and internal zones are counted separately, each with a default quota of 1,000,000 records.

    Accounts without an account-level quota are unaffected: existing per-zone quotas behave exactly as before.

    For more details, refer to DNS records quota.

  • WAF – WAF Release – 2026-06-09

    This release introduces new detections for a critical SQL injection vulnerability in Drupal installations utilizing PostgreSQL (CVE-2026-9082), alongside targeted protection for an unsafe deserialization flaw in the Mirasvit Cache Warmer extension (CVE-2026-45247). Additionally, this release includes coverage for a prototype pollution vector in Axios (CVE-2026-40175) and a new generic rule designed to identify and block sophisticated SQL Injection (SQLi) bypass attempts leveraging obfuscated boolean logic.

    Key Findings

    • CVE-2026-9082: A database abstraction vulnerability affects Drupal sites configured with a PostgreSQL backend. Remote, unauthenticated attackers can exploit this flaw via crafted inputs to inject malicious SQL commands and access or manipulate backend data.

    • CVE-2026-45247: A PHP Object Injection vulnerability exists in the Mirasvit Cache Warmer extension for Magento and Adobe Commerce. This flaw stems from unsafe deserialization of untrusted user input, enabling unauthenticated attackers to execute arbitrary code on the hosting server.

    • CVE-2026-40175: A prototype pollution vulnerability affects the Axios HTTP client library. Attackers can exploit this to inject malicious properties into the global JavaScript object prototype, potentially causing application crashes (Denial of Service) or executing unauthorized code depending on the application structure.

    Impact

    Successful exploitation of these vulnerabilities could allow unauthenticated attackers to execute arbitrary code, manipulate database contents, or induce application crashes, leading to severe operational disruption or complete server compromise. These newly deployed signatures intercept these advanced malicious payloads at the edge before they can interact with vulnerable software configurations.

    Ruleset Rule ID Legacy Rule ID Description Previous Action New Action Comments
    Cloudflare Managed Ruleset b4f88cb767874def810edd0b387cf935 N/A Axios – Prototype Pollution – CVE:CVE-2026-40175 Log Block

    This is a new detection.

    Cloudflare Managed Ruleset 098997bb8b5f48abb4039bd6417eb9e0 N/A Drupal – PostgreSQL SQLi – CVE:CVE-2026-9082 – Body Log Block

    This is a new detection.

    Cloudflare Managed Ruleset 8a7650b99ec04a91a19b8295fd3857fd N/A Drupal – PostgreSQL SQLi – CVE:CVE-2026-9082 – URI Log Block

    This is a new detection.

    Cloudflare Managed Ruleset 525c0871787840e6a6193f6caee241d2 N/A SQLi – Obfuscated Boolean – Body N/A Disabled

    This is a new detection.

    Cloudflare Managed Ruleset 1ec4aeaf7900463397b82b35d8620070 N/A SQLi – Obfuscated Boolean – Headers N/A Disabled

    This is a new detection.

    Cloudflare Managed Ruleset fb74766654c44ff2a5204dc4e0be4d47 N/A Mirasvit Cache Warmer – PHP Object Injection – CVE:CVE-2026-45247 N/A Block

    This is a new detection.

  • Realtime – Post-meeting transcriptions are now Generally Available in RealtimeKit

    RealtimeKit lets you build products where people meet over live audio and video — such as HealthTech, EdTech, proctoring, and other real-time platforms — on Cloudflare’s global WebRTC infrastructure.

    Post-meeting transcription is now Generally Available, so completed RealtimeKit meetings can automatically produce full transcript files after they end. Those transcripts can also power AI-generated summaries for meeting notes, review workflows, and follow-up tasks after the transcript is available.

    Post-meeting transcription is a managed service powered by Workers AI using Whisper Large v3 Turbo. RealtimeKit handles transcription processing and can return transcript and summary files through webhooks or the REST API, so you do not need to run your own transcription infrastructure.

    Generate transcripts and summaries

    To generate a transcript after a meeting ends, set transcribe_on_end: true when creating a meeting. To also generate an AI summary automatically after the transcript is available, set summarize_on_end: true:

    curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/realtime/kit/$APP_ID/meetings"
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
    -H "Content-Type: application/json"
    -d '{
    "title": "Weekly product review",
    "transcribe_on_end": true,
    "summarize_on_end": true,
    "ai_config": {
    "transcription": {
    "language": "en"
    },
    "summarization": {
    "word_limit": 500,
    "text_format": "markdown",
    "summary_type": "team_meeting"
    }
    }
    }'

    Consume results

    When RealtimeKit finishes processing a meeting, it creates download URLs for the transcript and, if summarize_on_end is set, the summary. You can receive those URLs automatically with webhooks, or fetch them later for a specific session with the REST API.

    To receive results as soon as they are ready, configure the meeting.transcript and meeting.summary webhook events:

    curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/realtime/kit/$APP_ID/webhooks"
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
    -H "Content-Type: application/json"
    -d '{
    "name": "AI results webhook",
    "url": "https://example.com/webhook",
    "events": ["meeting.transcript", "meeting.summary"],
    "enabled": true
    }'

    To fetch results later, call the transcript or summary endpoint for the session:

    curl -X GET "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/realtime/kit/$APP_ID/sessions/$SESSION_ID/transcript"
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
    curl -X GET "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/realtime/kit/$APP_ID/sessions/$SESSION_ID/summary"
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"

    Use the Generate summary of transcripts for the session API only if summarize_on_end was not set and you want to generate a summary manually after the transcript is available:

    curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/realtime/kit/$APP_ID/sessions/$SESSION_ID/summary"
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"

    Post-meeting transcription supports CSV, JSON, SRT, and VTT transcript outputs, automatic language detection and Whisper language codes. RealtimeKit also supports real-time transcription with Deepgram Nova-3 for live captions, in-meeting accessibility, and real-time note-taking.

    Learn more in the RealtimeKit transcription docs and summary docs.

  • R2 SQL – R2 SQL now supports UNION, INTERSECT, EXCEPT, and SELECT DISTINCT

    R2 SQL now supports set operations (UNION, INTERSECT, EXCEPT) and SELECT DISTINCT, expanding the range of analytical queries you can run directly on Apache Iceberg tables in R2 Data Catalog.

    Set operations

    Combine the results of multiple SELECT statements:

    • UNION — returns all rows from both queries, removing duplicates
    • UNION ALL — returns all rows from both queries, including duplicates
    • INTERSECT — returns only rows that appear in both queries
    • EXCEPT — returns rows from the first query that do not appear in the second
    -- Find zones that had either firewall blocks OR high-risk requests
    SELECT zone_id FROM my_namespace.firewall_events WHERE action = 'block'
    UNION
    SELECT zone_id FROM my_namespace.http_requests WHERE risk_score > 0.8
    -- Find zones with both firewall blocks AND high traffic
    SELECT zone_id FROM my_namespace.firewall_events WHERE action = 'block'
    INTERSECT
    SELECT zone_id FROM my_namespace.http_requests
    GROUP BY zone_id
    HAVING COUNT(*) > 10000
    -- Find enterprise zones that have not been compacted
    SELECT zone_id FROM my_namespace.zones WHERE plan = 'enterprise'
    EXCEPT
    SELECT zone_id FROM my_namespace.compaction_history

    Select distinct

    Eliminate duplicate rows from query results:

    SELECT DISTINCT region, department
    FROM my_namespace.sales_data
    WHERE total_amount > 1000
    ORDER BY region, department
    LIMIT 100

    For large datasets where approximate results are acceptable, approx_distinct() remains a faster alternative for counting unique values.

    For the full syntax reference, refer to the SQL reference. For performance guidance, refer to Limitations and best practices.

  • Email Service – Authenticated SMTP submission now available in beta

    You can now send emails through Cloudflare Email Service using authenticated SMTP submission on smtp.mx.cloudflare.net:465. SMTP joins the REST API and the Workers binding as a third way to send transactional email — useful for existing applications that already speak SMTP and language-native SMTP libraries (Nodemailer, smtplib, PHPMailer, JavaMail).

    Setting Value
    Host smtp.mx.cloudflare.net
    Port 465 (implicit TLS)
    AUTH PLAIN or LOGIN
    Username api_token
    Password A Cloudflare API token (account-owned or user-owned) with Email Sending: Edit

    Submissions enter the same delivery pipeline as the REST API and Workers binding: identical limits, automatic DKIM and ARC signing, and shared dashboard logs.

    Send your first email with a single command:

    curl --ssl-reqd
    --url "smtps://smtp.mx.cloudflare.net:465"
    --user "api_token:<API_TOKEN>"
    --mail-from "[email protected]"
    --mail-rcpt "[email protected]"
    --upload-file mail.txt

    Refer to the SMTP reference for authentication details, response codes, and language-specific examples.

  • Realtime – Post-meeting transcriptions are now Generally Available in RealtimeKit

    RealtimeKit lets you build products where people meet over live audio and video — such as HealthTech, EdTech, proctoring, and other real-time platforms — on Cloudflare’s global WebRTC infrastructure.

    Post-meeting transcription is now Generally Available, so completed RealtimeKit meetings can automatically produce full transcript files after they end. Those transcripts can also power AI-generated summaries for meeting notes, review workflows, and follow-up tasks after the transcript is available.

    Post-meeting transcription is a managed service powered by Workers AI using Whisper Large v3 Turbo. RealtimeKit handles transcription processing and can return transcript and summary files through webhooks or the REST API, so you do not need to run your own transcription infrastructure.

    Generate transcripts and summaries

    To generate a transcript after a meeting ends, set transcribe_on_end: true when creating a meeting. To also generate an AI summary automatically after the transcript is available, set summarize_on_end: true:

    curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/realtime/kit/$APP_ID/meetings"
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
    -H "Content-Type: application/json"
    -d '{
    "title": "Weekly product review",
    "transcribe_on_end": true,
    "summarize_on_end": true,
    "ai_config": {
    "transcription": {
    "language": "en"
    },
    "summarization": {
    "word_limit": 500,
    "text_format": "markdown",
    "summary_type": "team_meeting"
    }
    }
    }'

    Consume results

    When RealtimeKit finishes processing a meeting, it creates download URLs for the transcript and, if summarize_on_end is set, the summary. You can receive those URLs automatically with webhooks, or fetch them later for a specific session with the REST API.

    To receive results as soon as they are ready, configure the meeting.transcript and meeting.summary webhook events:

    curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/realtime/kit/$APP_ID/webhooks"
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
    -H "Content-Type: application/json"
    -d '{
    "name": "AI results webhook",
    "url": "https://example.com/webhook",
    "events": ["meeting.transcript", "meeting.summary"],
    "enabled": true
    }'

    To fetch results later, call the transcript or summary endpoint for the session:

    curl -X GET "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/realtime/kit/$APP_ID/sessions/$SESSION_ID/transcript"
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
    curl -X GET "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/realtime/kit/$APP_ID/sessions/$SESSION_ID/summary"
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"

    Use the Generate summary of transcripts for the session API only if summarize_on_end was not set and you want to generate a summary manually after the transcript is available:

    curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/realtime/kit/$APP_ID/sessions/$SESSION_ID/summary"
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"

    Post-meeting transcription supports CSV, JSON, SRT, and VTT transcript outputs, automatic language detection and Whisper language codes. RealtimeKit also supports real-time transcription with Deepgram Nova-3 for live captions, in-meeting accessibility, and real-time note-taking.

    Learn more in the RealtimeKit transcription docs and summary docs.

  • R2 SQL – R2 SQL now supports UNION, INTERSECT, EXCEPT, and SELECT DISTINCT

    R2 SQL now supports set operations (UNION, INTERSECT, EXCEPT) and SELECT DISTINCT, expanding the range of analytical queries you can run directly on Apache Iceberg tables in R2 Data Catalog.

    Set operations

    Combine the results of multiple SELECT statements:

    • UNION — returns all rows from both queries, removing duplicates
    • UNION ALL — returns all rows from both queries, including duplicates
    • INTERSECT — returns only rows that appear in both queries
    • EXCEPT — returns rows from the first query that do not appear in the second
    -- Find zones that had either firewall blocks OR high-risk requests
    SELECT zone_id FROM my_namespace.firewall_events WHERE action = 'block'
    UNION
    SELECT zone_id FROM my_namespace.http_requests WHERE risk_score > 0.8
    -- Find zones with both firewall blocks AND high traffic
    SELECT zone_id FROM my_namespace.firewall_events WHERE action = 'block'
    INTERSECT
    SELECT zone_id FROM my_namespace.http_requests
    GROUP BY zone_id
    HAVING COUNT(*) > 10000
    -- Find enterprise zones that have not been compacted
    SELECT zone_id FROM my_namespace.zones WHERE plan = 'enterprise'
    EXCEPT
    SELECT zone_id FROM my_namespace.compaction_history

    Select distinct

    Eliminate duplicate rows from query results:

    SELECT DISTINCT region, department
    FROM my_namespace.sales_data
    WHERE total_amount > 1000
    ORDER BY region, department
    LIMIT 100

    For large datasets where approximate results are acceptable, approx_distinct() remains a faster alternative for counting unique values.

    For the full syntax reference, refer to the SQL reference. For performance guidance, refer to Limitations and best practices.

  • Workflows – Rollback support now available in Workflows

    Workflows now supports saga-style rollbacks, allowing you to add compensating logic to each step.do() in case of downstream failures. If the instance fails, the rollback handlers will execute in reverse step-start order.

    This is useful for multi-step operations that touch external systems, such as inventory reservations, payment authorization, ticket creation, or infrastructure provisioning. Instead of writing all cleanup logic in a top-level catch, you can keep each compensating action next to the step it undoes.

    Rollback handlers support their own retry and timeout configuration, and Workflows now exposes rollback outcomes in instance status responses. Workflows analytics also emits rollback lifecycle events, making it easier to distinguish a forward execution failure from a rollback failure when debugging production workflows.

    • JavaScript

      await step.do(
      "provision resource",
      async () => {
      const resource = await provisionResource();
      return { resourceId: resource.id };
      },
      {
      rollback: async ({ output }) => {
      const { resourceId } = output;
      await deleteResource(resourceId);
      },
      rollbackConfig: {
      retries: { limit: 3, delay: "15 seconds", backoff: "linear" },
      timeout: "2 minutes",
      },
      },
      );
    • TypeScript

      await step.do(
      "provision resource",
      async () => {
      const resource = await provisionResource();
      return { resourceId: resource.id };
      },
      {
      rollback: async ({ output }) => {
      const { resourceId } = output as { resourceId: string };
      await deleteResource(resourceId);
      },
      rollbackConfig: {
      retries: { limit: 3, delay: "15 seconds", backoff: "linear" },
      timeout: "2 minutes",
      },
      },
      );

    Refer to rollback options to learn more.

  • Workflows – Rollback support now available in Workflows

    Workflows now supports saga-style rollbacks, allowing you to add compensating logic to each step.do() in case of downstream failures. If the instance fails, the rollback handlers will execute in reverse step-start order.

    This is useful for multi-step operations that touch external systems, such as inventory reservations, payment authorization, ticket creation, or infrastructure provisioning. Instead of writing all cleanup logic in a top-level catch, you can keep each compensating action next to the step it undoes.

    Rollback handlers support their own retry and timeout configuration, and Workflows now exposes rollback outcomes in instance status responses. Workflows analytics also emits rollback lifecycle events, making it easier to distinguish a forward execution failure from a rollback failure when debugging production workflows.

    • JavaScript

      await step.do(
      "provision resource",
      async () => {
      const resource = await provisionResource();
      return { resourceId: resource.id };
      },
      {
      rollback: async ({ output }) => {
      const { resourceId } = output;
      await deleteResource(resourceId);
      },
      rollbackConfig: {
      retries: { limit: 3, delay: "15 seconds", backoff: "linear" },
      timeout: "2 minutes",
      },
      },
      );
    • TypeScript

      await step.do(
      "provision resource",
      async () => {
      const resource = await provisionResource();
      return { resourceId: resource.id };
      },
      {
      rollback: async ({ output }) => {
      const { resourceId } = output as { resourceId: string };
      await deleteResource(resourceId);
      },
      rollbackConfig: {
      retries: { limit: 3, delay: "15 seconds", backoff: "linear" },
      timeout: "2 minutes",
      },
      },
      );

    Refer to rollback options to learn more.