This repository shows how to securely intercept and handle browser network requests containing cardholder data. Instead of a traditional proxy, it listens for outgoing requests in the browser, detects sensitive payloads, and securely recreates them using Basis Theory Reactors inside a managed Cardholder Data Environment (CDE).
By outsourcing the CDE to Basis Theory, platforms can reduce PCI scope, simplify compliance, and avoid building their own secure infrastructure. This example lets agents (human or bot) enter fake card numbers, intercepts the request, replaces the data with tokenized card information, and completes the transaction securely.
This example uses Puppeteer for request interception and fulfillment, but developers can adapt the approach to any browser stack or tool suitable for their needs.
sequenceDiagram
actor A as Agent<br>(Person/Bot)
participant B as Browser
box rgba(84, 110, 150, 100) Browser Driver
participant P as Puppeteer
participant R as Basis Theory<br>Reactor
end
participant M as Merchant<br>Checkout
A->>B: Enters fake card number on checkout page
B->>P: Sends network request with fake card data
P->>P: Intercepts request
P->>R: Forwards request with {{ token }}
R->>R: Detokenizes card data
opt Optional
R->>R: Manipulates request
end
R->>M: Recreates and sends request with real card data
M-->>R: Returns transaction response
R-->>P: Returns transaction response
P-->>B: Fulfills the response
B-->>A: Displays transaction confirmation
- A Basis Theory account
- Terraform
- Node.js
- Yarn
-
Create a Management Application
You need an API key withreactor:*andapplication:*permissions.👉 Click here to create an application using the Customer Portal
-
Configure Terraform variables
cp terraform.tfvars.example terraform.tfvars # Paste your Management API key in terraform.tfvars under BT_MANAGEMENT_API_KEY -
Configure Node variables
cp .env.example .env # Paste your card token id under TOKEN_ID💡 If you don't have a card token created yet, check out our the Tokens API spec or get started with one of our Guides.
-
Initialize your Terraform workspace:
terraform init
-
Apply your Terraform configuration:
terraform apply
-
Install Node dependencies:
yarn install
Launch the browser connected to Puppeteer using the command below:
yarn startNow navigate to the merchant checkout page, enter a fake card number, and see the magic happen.
A Matcher is a JavaScript module that intercepts and handles specific network requests. Each matcher defines two core functions: match() to identify relevant requests and handle() to process them securely.
export default {
match: (request) => boolean,
handle: async (request) => response
}- Purpose: Determines if this matcher should handle the intercepted request
- Parameters:
request.url(string): The request URLrequest.method(string): HTTP method (GET, POST, PUT, etc.)request.headers(object): Request headersrequest.postData(string): Request body
- Returns:
boolean-trueif this matcher should handle the request
- Purpose: Processes the matched request by tokenizing sensitive data and forwarding to a Basis Theory Reactor
- Parameters: Same as
match()function - Returns:
Promise<response>- Response object with:status(number): HTTP status codeheaders(object): Response headersbody(string): Response body
-
Create a new file in
src/matchers/(e.g.,yourService.js) -
Implement the matcher structure with
match()andhandle()functions -
Register the matcher in
src/matchers/index.jsby importing and adding to the matchers array
Use Basis Theory detokenization expressions to securely replace sensitive data:
{{ token: TOKEN_ID }}- Use the entire token value{{ token: TOKEN_ID | json: "$.data.number" }}- Extract specific field from token data{{ token: TOKEN_ID | json: "$.data" | card_exp: "MM" }}- Format card expiration month{{ token: TOKEN_ID | json: "$.data" | card_exp: "YYYY" }}- Format card expiration year
Ensure you have the required environment variables:
TOKEN_ID: Your card token IDYOUR_REACTOR_ID: Your Basis Theory Reactor IDBROWSER_APPLICATION_KEY: Your Basis Theory Private API keyBT_API_URL: Basis Theory API URL (e.g. "https://api.basistheory.com")
A Reactor is server-side code that runs inside the Basis Theory Cardholder Data Environment (CDE). It receives tokenized data from matchers, detokenizes it securely, and forwards the request to the actual merchant API.
- Plain Reactor: Use when the request can be fully formatted at the client side with token expressions. The plain reactor simply forwards the request with detokenized data.
- Custom Reactor: Create a new reactor when you need to manipulate the request format, encrypt data, or perform additional processing inside the CDE.
const axios = require('axios');
module.exports = async function (req) {
const {
configuration: { /* your config vars */ },
args: {
request: { url, method, headers, data }
}
} = req;
// Your processing logic here
const res = await axios({
method,
url,
headers,
data,
validateStatus: () => true
});
return {
raw: {
status: res.status,
headers: res.headers,
data: res.data
}
};
}For detailed parameter specifications, see the Basis Theory Reactor API documentation.
- Create a new file in
src/reactors/(e.g.,yourService.js) - Add the reactor to Terraform in
main.tfwith configuration variables - Add the reactor ID output in
main.tf - Load the reactor ID in
src/utils/loadEnvVars.js - Add the variable to
terraform.tfvars.example
Reactor configuration variables are passed through the configuration object:
- Define them in
main.tfunder the reactor'sconfigurationblock - Add corresponding variables to
terraform.tfvars - Access them in your reactor code via
req.configuration.YOUR_VAR