Tencent (TSRC) — XSS Phase 1: Static & DOM Analysis

**Phase 2 update (2026-11-02):** the two candidates ranked here were tested under
approved read-only/minimal-touch rules and **both dead-ended** — see
`XSS_PHASE2_REPORT.md`. No confirmed DOM-XSS in either phase.

Target program: Tencent Security Response Center (TSRC)

Scope: *.mail.qq.com, *.exmail.qq.com, jiazhang.qq.com, doc.qq.com

Phase: 1 — static/passive only. HARD STOP on active scanning maintained.

Date: 2026-11-02 (UTC)

Author: operator-assisted agent run

---

0. Ground rules honoured

response header. Nothing is asserted from memory.

tencent/logs/phase1_commands.log (and the earlier tencent/server_commands.log).

Ground truth from `find/FINAL_RANKING.md` (verified earlier, not re-litigated):
Tencent score 55.00, no bonus. Prioritised hosts per that audit: app.mail.qq.com
(jQuery 1.10.2), jiazhang.qq.com (jQuery 1.11.3), doc.qq.com, and the
`*.exmail.qq.com` family (jQuery 1.11.0). `service.qq.com`, `fanyi.qq.com`,
`tenpay.com` are **out of scope** and were excluded.

---

1. Tools actually used (with versions)

ToolVersionWherePurpose
curl8.22localfetch HTML/JS + capture headers (polite, one request per asset)
python33.14.7local`analyze_sinks.py` static source→sink census; regex tracing
grep / awk / sortcoreutils, ripgreplocalbyte-offset sink context extraction
jq1.8.2localparse Cloudflare API JSON
sshOpenSSHlocal→serverserver admin for PoC infra
Caddyv2.11.7server 216.73.157.146PoC web server (TLS, logging)
Cloudflare APIv4localDNS record + Origin Rule for PoC host
dig, whatweb, httpx, subfinder(prior survey)localinventory provenance (see `xss_targets.csv`)

nuclei, nmap, ffuf, gobuster, amass were available but not run in

this phase — they are active tools and are out of scope until Phase 2 approval.

---

2. Inventory

tencent/xss_targets.csv — 14 rows, one per in-scope host, with priority,

in-scope basis, jQuery version, tech signals, live status, page URLs to analyse,

and the evidence file that established each version.

Priority order used for mirroring and analysis:

  1. app.mail.qq.com — jQuery 1.10.2 (oldest in scope)
  2. jiazhang.qq.com — jQuery 1.11.3
  3. doc.qq.com — 302 → docs.qq.com (no first-party content served)
  4. *.exmail.qq.com × 11 hosts — jQuery 1.11.0 (cnc, download, en, mail,

set1, set2, ssl, tel, tls, tp, xc)

---

3. Download & mirror

Mirrored under tencent/static/<host>/ (HTML + all first-party JS + response

headers for the entry page):

Host dirHTMLFirst-party JS
`static/app.mail.qq.com/``index.html` (137 991 B)`jquery-1.10.2.min.js`, `new.js`, `app_landing-web.js`, `vendor_page-web.js`
`static/jiazhang.qq.com/``index.html`, `index-m.html`, `index-ie.html`12 files incl. `jquery.js`, `index.js`, `superplayer.js`, `swiper.js`, `aq_common.js`, `beacon_web.js`, `reporter.js`, `animate.js`, `scroll-trigger.js`, `gsap.js`, `lazyload.min.js`, `aegis1.43.6.min.js`
`static/exmail.qq.com/``cnc.html` (50 766 B)`jquery-1.11.0.min462fc5.js`, `index74e89a.js`, `pkg74e89b.js`, `global7fa051.js`, `responsiveslides462fc5.js`
`static/doc.qq.com/``index.html` (137 B redirect stub)—

Response headers captured (see *.headers files). Behaviour-relevant results:

'unsafe-eval'; jiazhang has no CSP header at all (served by tencent-cos).

not set one.

(recorded for Phase 2, not claimed as a finding here).

---

4. Source → sink census

Tool: tencent/analyze_sinks.py (read-only, offline). Output:

tencent/logs/sink_census.txt (264 lines). Sources scanned: location.hash,

location.search, location.href, document.referrer, window.name,

postMessage, addEventListener("message"), URLSearchParams. Sinks scanned:

innerHTML, outerHTML, insertAdjacentHTML, document.write, eval,

setTimeout(string), .html(), .append(), .attr("href"|"src"|…),

createContextualFragment, .srcdoc, dangerouslySetInnerHTML.

Files tagged [UPSTREAM-LIB] (jQuery, Swiper, GSAP, lazyload, aegis,

vendor_page-web) were scanned but their internal matches are not app-level

findings.

Full ranked table with offsets and confidence:

tencent/xss_candidates.md. Summary of what the census proved:

location.href for telemetry; its jsonp token is a hardcoded

cube.weixinbridge.com beacon, not a script load.

BroadcastChannel.onmessage handlers are Bluebird's task scheduler and Axios's

async trampoline, both with self-source equality checks. No app message sink.

document.domain="qq.com" iframe trampoline; postMessage is an internal

bridge bus; DBF location.hash/document.referrer reads feed telemetry only.

it to slide data-hash; no HTML sink.

location.search to a fixed static target (./index-m.html, ./index-ie.html).

No DOM sink; at most a nuisance redirect (query string preserved).

($(".index_hot_wrap").html(n.data.hot_log_html)), fed by AJAX

/qy_mng_logic/wwhelp.

used only as an AJAX data param and in a string compare; no DOM sink.

document.write, innerHTML, insertAdjacentHTML); a control, not a sink.

---

5. jQuery gadget / CVE-2015-9251 check

All three jQuery copies are < 3.0.0, so they *contain* the CVE-2015-9251

cross-domain-AJAX→script path:

HostFileVersion
app.mail.qq.com`static/app.mail.qq.com/js/jquery-1.10.2.min.js`v1.10.2
jiazhang.qq.com`static/jiazhang.qq.com/js/jquery.js`v1.11.3
*.exmail.qq.com`static/exmail.qq.com/js/jquery-1.11.0.min462fc5.js`v1.11.0

Verdict: present-but-untriggered. Library internals expose getScript and

dataType:"script", but a scan of every first-party app file found zero

callers passing a user-controlled URL, and zero classic JSONP callback=?

sinks. Likewise, no $(userInput) selector-injection call site exists in app

code (all selectors are string literals or this).

---

6. Live PoC infrastructure

Goal: a report-verifiable test host reachable from anywhere (not just the local

machine), with timestamped request logging.

Host: https://tencent-poc.msedigh.lol → Cloudflare (proxied) → origin

216.73.157.146:8443 (Caddy).

Setup (all verified live):

(record id 7001d447b1b86add4b56bf90a52dedf2), set to proxied.

(phase http_request_origin): (http.host eq "tencent-poc.msedigh.lol") →

origin port 8443. Existing rules preserved (diff vs /tmp/origin_rules_before.json

showed only the added rule).

(/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/tencent-poc.msedigh.lol).

(http-01 solved after the DNS record was briefly set to DNS-only for validation.)

/etc/caddy/Caddyfile.bak-tencentpoc-20261102T132246Z):

`

tencent-poc.msedigh.lol:8443 {

log { output file /var/log/caddy/tencent-poc-access.log format json }

root * /srv/tencent-poc

handle /collect { reverse_proxy 127.0.0.1:8780 }

handle { file_server }

}

`

by the VLESS/xray inbound, so the PoC serves on origin port 8443 (already

allowed and already used by cors-proof.msedigh.lol).

VLESS tunnel integrity check (post-reload): port 443 still owned by

xray-linux-amd64; all xray processes alive; Reality handshake still returns the

camo certificate. Tunnel intact.

Request logging: every hit is written as JSON to

/var/log/caddy/tencent-poc-access.log (path, query, headers, remote IP, time).

The root-level POST /collect path proxies to the existing collector

(127.0.0.1:8780, cors-proof-collector.service) for canary/callback capture; it is

POST-only (a bare GET returns 501, a malformed POST returns 400 — verified).

How to operate it:

served at https://tencent-poc.msedigh.lol/poc/<file>.

(see the collector's expected payload shape before use).

systemctl reload caddy.

---

7. Honest outcome & Phase-2 ranking

No confirmed DOM-based XSS was found in this static phase. This is an

acceptable Phase-1 result: the mirrored first-party code contains no

attacker-controlled source→executing-sink path *at rest*.

Most promising candidates for a **controlled, TSRC-compliant Phase 2 verification

round (needs explicit operator approval before any active test):**

  1. exmail $(".index_hot_wrap").html(n.data.hot_log_html) — the only genuine

executing HTML sink. Phase-2 question: can the /qy_mng_logic/wwhelp response

body be influenced (parameter, cache, or account-side data)? Investigate the

endpoint contract read-only first.

  1. jiazhang client-side redirect with location.search — low value, but the

query string is carried into a redirect; worth a read-only check whether any

downstream page reflects it (e.g. index-ie.html / index-m.html).

  1. jQuery 1.10/1.11 gadget surface — none found in app code; only re-open if a

new first-party module that calls $.getScript/JSONP with user input is

discovered in a future crawl.

Explicitly not findings (recorded so we do not re-litigate):

X-Frame-Options, referrer-policy differences — posture observations only.

assignment).

---

8. Gaps / not covered

mirrored. Deeper app routes (logged-in app.mail.qq.com states, exmail account

pages behind auth) were not touched — that requires an operator-owned test

account and explicit authorisation.

representative. Per-host divergence was not exhaustively diffed.

were not mirrored (they are first-party CDN, but the review focused on

origin-served app code).

docs.qq.com is in TSRC scope before spending time there.

load; deferred to Phase 2).

---

9. Evidence index

ArtifactPath
Inventory`tencent/xss_targets.csv`
Candidate table`tencent/xss_candidates.md`
Sink census`tencent/logs/sink_census.txt`
Analyzer`tencent/analyze_sinks.py`
Command log`tencent/logs/phase1_commands.log`, `tencent/server_commands.log`
Mirrored assets`tencent/static/<host>/`
Captured headers`tencent/static/*/*.headers`, `tencent/evidence/`
This report (HTML)`https://tencent-poc.msedigh.lol/poc/report.html`