Is TecWorld Descontos safe?

Medium risk

TecWorld Descontos sends checkout-page URLs and selected page values to descontos.tecworld.com.br.

When a visited store matches its remote flow configuration, TecWorld Descontos records the current page URL and extracts configured values from the page, scripts, or text patterns. It base64-encodes that flow history and collected values, then posts them to TecWorld's flow endpoint.

tecworld.pluginv9.28.0Chrome Web Store
45Risk

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

TecWorld Descontos sends your checkout page URL and order details to itself

We observed the extension send the checkout confirmation page URL, store ID, and order fields to TecWorld's own server after visiting Netshoes and Centauro.

The same live config flags five more partner retailers.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-359
Source
Dynamic sandbox
What actually happens
You did this

You reach a checkout confirmation page at a store the extension's live remote config currently flags, such as Netshoes, Centauro, or Carrefour.

The extension did this

The extension records the page's URL and any order fields the config requests, then uploads them to TecWorld's own server.

What gets uploaded on a matched checkout page
  • Checkout page URL
    https://www.netshoes.com.br/checkout/payment/confirm/123456789

    The full address of the order confirmation page you land on right after paying, order number included.

  • Store ID
    store_id=5 (Netshoes)

    A numeric ID for which retailer's checkout page matched, taken from the vendor's own store catalog.

  • Order / purchase data
    ecommerce.purchase.actionField.id (read via dataLayer, per Netshoes' own live config)

    On other configured stores, the config also reads order or purchase details from the page's dataLayer or a CSS selector.

Captured request
POSThttps://descontos.tecworld.com.br/app/post/flow

200 OK, {"status":true}

Body
store_id=5&flow=<base64, decoded below>&values=<base64, decoded below>decoded flow:[{"ts":1788877534000,"type":"loc","value":"https://www.netshoes.com.br/checkout/payment/confirm/123456789"}]decoded values:{}
The code that does this

Deciding to scrape a page, then uploading what was collected

Readable version

index.js, renamed for readability

extracted/index.js
matchesFlowUrl = async (pageUrl, flowConfig) => {  if (!flowConfig.ativo) return null;                  // remote "ativo" flag must be 1  const urlRegex = new RegExp(flowConfig.url, "i");     // e.g. "netshoes\\.com\\.br\\/checkout\\/payment\\/confirm\\/\\d+"  return urlRegex.exec(pageUrl) ? await collectFields(flowConfig) : null;};collectFields = async (flowConfig) => {  const fieldSpecs = flowConfig.data || [];  const collected = {};  for (const spec of fieldSpecs) {    collected[spec.nome] = await extractOneField(spec);  // e.g. "order"  }  return collected;};extractOneField = async (spec) => {  let value = null;  if (spec.script_selector) value = await readJsonFromScriptTag(spec);  // JSON inside a <script> tag  if (spec.script_var)      value = await readWindowVariable(spec);     // e.g. window.dataLayer  if (spec.selector)        value = await readDomText(spec);            // jQuery selector -> .text()  if (spec.regex)           value = await extractByRegex(spec);         // regex over page HTML  return value;};

background.js, renamed for readability

extracted/background.js
getStoredFlow = (storeId) => memcache.get(`flow:${storeId}`);sendFlow = async (storeId, collectedFields) => {  const flowRecord = getStoredFlow(storeId);  const locationHistory = await flowRecord.getAll();  // [{ts, type: 'loc', value: pageUrl}, ...]  const payload = {    store_id: storeId,    flow: btoa(JSON.stringify(locationHistory)),    values: btoa(JSON.stringify(collectedFields)),  };  return api.post('app/post/flow', payload, { ttl: DEFAULT_TTL });};
What we did and didn't capture directly

The URL upload is confirmed live on Netshoes and Centauro. Order/purchase-field extraction is the same code path and is live-armed in the config for five more retailers, but our test pages had no real checkout content to read.

Reproduce it yourself

Decodes the base64 flow and values form fields from a captured POST to TecWorld's app/post/flow endpoint into readable JSON.

Requires
  • Node.js 18+
tecworld-flow-decode.js · js
#!/usr/bin/env node// Decodes the base64 "flow" and "values" form fields TecWorld Descontos// POSTs to https://descontos.tecworld.com.br/app/post/flowconst [flowB64, valuesB64] = process.argv.slice(2);if (!flowB64) {  console.error('Usage: node tecworld-flow-decode.js <flow_base64> [values_base64]');  process.exit(1);}const decode = (b64) => JSON.parse(Buffer.from(b64, 'base64').toString('utf8'));console.log('flow (location history):');console.log(JSON.stringify(decode(flowB64), null, 2));if (valuesB64) {  console.log('\nvalues (collected page fields):');  console.log(JSON.stringify(decode(valuesB64), null, 2));}
How to run it
  1. 1node tecworld-flow-decode.js '<flow_base64>' '<values_base64>'
Where the data ends up
    • descontos.tecworld.com.br

    TecWorld's own backend. Receives the checkout page URL and any configured order fields for stores its remote config currently flags as active.

What it can do

Permissions this extension asks for, as declared in version 9.28.0. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.

  • Read and change your data on descontos.tecworld.com.br

    https://descontos.tecworld.com.br/**/*

  • Sign you in with your Google account

    identity

Where it sends data

Destinations our analysis observed TecWorld Descontos contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.

  • descontos.tecworld.com.br

    TecWorld Descontos sends data to descontos.tecworld.com.br. No other extension we have analysed sends data here.

Updated 30 September 2026aopiblpdipgmiiafojaigmoalfmboidh