Other peoples' details pre-filled in cart when new user purchases products

These details showed up when user was purchasing a product, these are not his details. And he has never typed in these details before. Please advise what’s wrong with address step details and how does it possible? There is a guest purchase.

    <div class="row mt-4">
    <div class="col-md-6 col-xs-12 mb-4">
        <form method="POST" action="{{ current_url }}">
            <input type="hidden" name="add_address" value="1">

            <input type="hidden"
                name="billing_address"
                value="new"
                checked="checked"
            >

            <input type="hidden" name="address[billing][properties][update_profile]" value="1" />

            <div class="form-floating mb-3 {% if error_billing_fullname %}error{% endif %}">
    <input type="text" class="form-control" name="address[billing][fullname]" id="address-billing-fullname" value="{{ address_billing_fullname }}">
    <label for="address-billing-fullname">{{ lex('commerce.address.name') }}</label>
    {% if error_billing_fullname %}<small class="text-danger">{{ error_billing_fullname }}</small>{% endif %}
</div>

    <div class="form-floating mb-3 {% if error_billing_email %}error{% endif %}">
        <input type="text" class="form-control" name="address[billing][email]" id="address-shipping-email" value="{{ address_shipping_email }}">
        <label for="address-billing-email">{{ lex('commerce.address.email') }}</label>
        {% if error_billing_email %}<small class="text-danger">{{ error_billing_email }}</small>{% endif %}
    </div>

    <div class="form-floating mb-3 {% if error_billing_address1 %}error{% endif %}">
        <input type="text" class="form-control" name="address[billing][address1]" id="address-billing-address1" value="{{ address_billing_address1 }}">
        <label for="address-billing-address1">{{ lex('commerce.address.address') }}</label>
        {% if error_billing_address1 %}<small class="text-danger">{{ error_billing_address1 }}</small>{% endif %}
    </div>

<div class="row">
    <div class="col-12 col-sm-6">
        <div class="form-floating mb-3">
            <input type="text" class="form-control" name="address[billing][zip]" id="address-billing-zip" value="{{ address_billing_zip }}">
           <label for="address-billing-zip">{{ lex('commerce.address.zip') }}</label>
            {% if error_billing_zip %}<small class="text-danger">{{ error_billing_zip }}</small>{% endif %}
        </div>
    </div>
    <div class="col-12 col-sm-6">
        <div class="form-floating mb-3">
            <input type="text" class="form-control" name="address[billing][city]" id="address-billing-city" value="{{ address_billing_city }}">
            <label for="address-billing-city">{{ lex('commerce.address.city') }}</label>
            {% if error_billing_city %}<small class="text-danger">{{ error_billing_city }}</small>{% endif %}
        </div>
    </div>
</div>
<input type="hidden" name="address[billing][remember]" id="address-billing-remember" value="1" checked="checked">
<input type="hidden" name="address[billing][country]" id="address-billing-country" value="GB">
<input type="hidden" name="address[billing][address2]" id="address-billing-address2" value="">
<input type="hidden" name="address[billing][state]" id="address-billing-state" value="">
<input type="hidden" name="address[billing][company]" id="address-billing-company" value="">
<input type="hidden" name="address[billing][properties][vat_registration]" id="address-billing-vat-registration" value="">

            <div class="row">
			    <div class="col">
                    <button type="submit" class="btn btn-primary btn-lg" style="width:100%;">{{ lex('commerce.checkout_address_confirm') }}</button>
                </div>
            </div>
        </form>
    </div>

If Commerce is pre-filling other peoples’ info that certainly would be a problem, however I do not see how that is possible.

The address_billing_* and address_shipping_* placeholders get filled from one of the following sources:

  1. What the customer has entered for their current order
  2. What the customer has chosen as their previous address (only logged-in customers)
  3. What is pre-filled by modules such as Default Address, AutoFillGeoIP, or UserProfileAddress. The first two of those are limited to state and country, the latter takes from the logged-in customer’s profile.

For that to get information from another customer, the entire session would need be taken over (as that will hold order information). There’s also a Commerce-specific order cookie, however that’s 128 characters long so even less likely to be taken over. Accidental collisions are mathmatically less likely to happen than, say, getting struck by lightning.

Honestly the only feasible way I can see the behavior you describe is some kind of caching, especially outside of MODX. Perhaps something like Varnish or CloudFlare in front of the webserver that’s serving repeat requests from an intermediate cache, without realising the checkout is user-specific. Even if such a cache is very short lived (like a few seconds), that could cause it to leak this information to someone else.

While MODX usually sends the appropriate nocache headers to indicate pages are dynamically generated, a cache can decide to ignore that and may need to be re-configured so it doesn’t cache the cart, checkout, etc.

Thanks, Mark! Will test that deeper, now in incognito mode I see other user details…the only thing is we hide country field and default “GB” value is used for all users now, you’ve mentioned the country above, will try to change it, maybe this will help. All other settings are the same as before. Website is located on MODXcloud. It seems I see colleague personal data, although we’re in different countries, and both testing via incognito mode.

P.S. we’ve disabled account step and guest user can purchase products without mandatory registration/signing in, that’s how Address page works now.

Any custom modules on that site?

The only core extension that sets more than a country or state to the expected address is the UserProfileAddress one, which relies on being logged-in (that uses $modx->user). So that there’s a full address in incognito mode suggests to me something custom…?

Morning Mark,
I’ve disabled one custom module, some custom plugins and noticed UserProfileAddress is the reason - when I disable it for Live mode form is empty. Is it a bug? We operate with guest users via incognito cart, so maybe some additional conditions will be needed for UserProfileAddress? Previously I’ve got other registered user details(using incognito mode).

I honestly do not see any way for the UserProfileAddress module to get information from another user. That uses $modx->user so relies on MODX to determine the user for the request based on session cookies and such. There isn’t really any extra condition to apply to that.

Can you email support@modmore.com with a login so I can try to debug this?