Symfony Panther - Access a secure iframe?

Viewed 384

I am trying to use Panther in my Symfony 5 app to fill out a Stripe payment form. My Stripe fields are managed by Stripe itself from iframes generated in my form.

(Take a look on the second example of the Stripe Elements form examples : https://stripe.dev/elements-examples/ , the fields are in Stripe hosted iframe. This is the same thing for my own form) enter image description here

enter image description here

<form>

  // input in main iframe
  <div class='row'>
  <div class='field'>
      <input id="example2-address" data-tid="elements_examples.form.address_placeholder" class="input empty" type="text" placeholder="185 Berry St" required="" autocomplete="address-line1">
    </div>
  </div>
  
  //stripe iframe
  <div class='row'>
    <div class='field'>
      <iframe name='__privateStripeFrame9208'>
        <html>
          <body>
            <form class='ElementsApp is-empty'>
              <input class="InputElement is-empty Input Input--empty" autocomplete="cc-number" autocorrect="off" spellcheck="false" type="text" name="cardnumber" data-elements-stable-field-name="cardNumber" inputmode="numeric" aria-label="Credit or debit card number" placeholder="1234 1234 1234 1234" aria-invalid="false" value="">
            </form>
          </body>
        </html>
      </iframe>
    </div>
  </div>
</form>

//Get iframe
$creditCardFrame = $this->client->findElement(WebDriverBy::cssSelector("#card-number > .__PrivateStripeElement > iframe"));

// returns : "iframe" and "__privateStripeFrame6225"
var_dump($creditCardFrame->getTagName(), $creditCardFrame->getAttribute('name'));

// Switch to iframe. (It should work no ?)
$this->client->switchTo()->frame($creditCardFrame);

// Trying to send keys in my own input (not a stripe field. It's on the default iframe). And I can.
$this->client->findElement(WebDriverBy::name('card-owner'))->sendKeys('my name');

// Trying to send keys in the cardnumber input (in a stripe iframe). Can't locate it.
$this->client->findElement(WebDriverBy::name('cardnumber'))->sendKeys("4242 4242 4242 4242");

These iframes seem protected, because when I switch to one of these iframes, it looks like I'm staying on my default frame and I can't access the frame of an input Stripe. In my opinion, this is because these are secure.

I would have liked to give you an error but the problem is that the switchTo() method is not programmed to return an error.

The only way to verify that it was successful is to try to fill in a field that is actually in that iframe, something I tried, giving me the error

"Could not locate element ..."

However, if I try to fill in a field that is in the default iframe, it works, which means the iframe change didn't happen.

As you can see in my code above, I'm making sure I'm pointing to an iframe with this:

// returns : "iframe" and "__privateStripeFrame6225"
var_dump($creditCardFrame->getTagName(), $creditCardFrame->getAttribute('name'));

I checked if this was the right way to do it, based on this issue https://github.com/symfony/panther/issues/446 , and I don't see why what I would do would be wrong.

So that's why I suspect that the iframe is secure, preventing me from accessing it

Is there a way to access it anyway?

1 Answers

There is no way to access the content of a Stripe Elements iframe. The iframes Stripe Elements uses are designed to prevent you from accessing their content by design in order to reduce your PCI compliance burden (emphasis added):

For users that have developed their own integration and are using either Checkout or Stripe.js and Elements to collect card details from customers, you are eligible for the simplest method of PCI validation: SAQ A. Stripe automatically creates a combined SAQ A and Attestation of Compliance (AoC) for you, available for you to download in your account’s compliance settings , and no action is required on your part to submit further proof of your PCI compliance.

This is possible because Checkout and Elements host all form inputs containing card data within an iframe served from Stripe’s domain—not yours—so your customers’ card information never touches your servers.

Browsers do not allow access to iframes from another origin by default. There are ways to get cross-origin communication working with iframes, but it requires the code inside the iframe to listen for and/or respond to messages sent to it, and Stripe's iframes do not have this code in place.

Related