Is 微信读书助手 safe?
微信读书助手 is high risk. When you open the popup after WeRead data is stored, it reads your WeRead VID and writes a persistent cookie scoped to qnmlgb.tech. Evidence confirms the cookie name, value source, domain, and an expiry about three years out.…
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
WeRead VID is copied into a qnmlgb.tech cookie
When you open the popup after WeRead data is stored, it reads your WeRead VID and writes a persistent cookie scoped to qnmlgb.tech.
Evidence confirms the cookie name, value source, domain, and an expiry about three years out.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Dynamic sandbox
You open the extension popup after logging in to WeRead.
The popup script runs automatically because manifest.json registers src/popup/popup.html as the browser-action popup.
The extension copies your stored WeRead VID into a long-lived qnmlgb.tech cookie.
The cookie is named vid, uses the value from userInfo.vid, and is scoped to .qnmlgb.tech.
- Cookie URLhttps://qnmlgb.tech
This points the browser at the qnmlgb.tech site when creating the cookie.
- Cookie domain.qnmlgb.tech
This lets the same identifier apply across matching qnmlgb.tech pages.
- Cookie namevid
This labels the stored identifier as the WeRead VID value.
- Cookie value1234567890 (illustrative WeRead VID)
This is your WeRead account identifier copied from extension storage into the cookie.
- Cookie lifetime1,095 days after the popup opens
This keeps the identifier available well beyond a normal browsing session.
Popup code path that writes the qnmlgb.tech cookie
Expiration helper after formatting
src/popup/popup.jsfunction getExpireTime() { return ((new Date).getTime() + 94608e6) / 1e3}Stored profile lookup and cookie write after formatting
src/popup/popup.jschrome.storage.local.get(["userInfo", "userShelf", "userCardSummary", "totalReadTime"], (function(e) { let t = e.userInfo, n = e.userShelf, o = e.userCardSummary, r = e.totalReadTime, i = 0; n && n.books && (i = n.books.length); let a = 0; if (o && o.expiredTime && (a = Math.max(0, parseInt((o.expiredTime - Date.parse(new Date) / 1e3) / 86400))), console.log("**popup**", e, a), t && t.vid) { console.log("**storage**", t); let e = $(`\n <a style="display: flex; flex-direction: row; justify-content: left; align-items: center;" href="https://weread.qq.com/" target="_blank">\n ${t.avatar&&t.avatar.length>0?`<img src="${t.avatar}" style="width: 20px; height: 20px; border-radius: 20px;" />`:'<div style="width: 20px; height: 20px; background-color: #e4e4e4; border-radius: 20px;"></div>'}\n <span style="margin-left: 5px; text-decoration: none; cursor: pointer; color: #259;">${t.name}</span>\n </a><div style="margin-top: 5px; color: #5d646e;">vid: ${t.vid}</div>\n ${a>=0?`<div style="margin-top: 5px; color: #5d646e;">无限卡剩余: <span style="font-weight: bold;">${a}</span> 天</div>`:""}\n <div style="margin-top: 5px; color: #5d646e;">本周阅读时长: ${getReadTimeStr(r)}</div>\n <div style="margin-top: 5px; color: #5d646e;">书架: <a href="shelf.html" style="margin: 0 3px;">${i}</a>本</div>\n `); $("#webook_user_info").prepend(e), t.vid && chrome.cookies.set({ url: "https://qnmlgb.tech", domain: ".qnmlgb.tech", name: "vid", value: t.vid.toString(), expirationDate: getExpireTime() }) } else { let e = $('\n <div style="display: flex; flex-direction: row; justify-content: left; align-items: center;">\n <a href="https://weread.qq.com/" target="_blank" style="text-decoration: none; cursor: pointer; color: #259;">⚡️ 前往登录微信读书</a>\n </div>\n '); $("#webook_user_info").prepend(e) }})),- qnmlgb.tech
Receives the vid cookie on matching qnmlgb.tech requests after the popup writes it.
- weread.qnmlgb.tech
Extension pages and popup links use this subdomain, and manifest permissions include *://*.qnmlgb.tech/*.
- webook.qnmlgb.tech
The popup fetches announcements from this subdomain and WeRead page code sends the stored VID as a request header for info lookups.
Popup renders remote announcement HTML without sanitization
When you open the popup, it requests announcement content from webook.qnmlgb.tech and inserts the response as HTML without sanitization, so active markup in that remote response could run in the popup context.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-829
- Source
- Dynamic sandbox
The user opens the extension popup.
The extension fetches announcement JSON from a remote server and renders the content field as HTML without sanitization.
- Announcement HTML content<p>Service notice</p> (illustrative)
HTML returned by the remote announcement service is inserted into the extension popup; active markup could run there.
User VID sent to WeRead helper server after popup submit click.
When you click the submit button in the extension popup, the extension reads the logged-in WeRead user VID from local extension storage.
It then sends that stored identifier as JSON to weread.qnmlgb.tech/submit.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
The user clicks the submit button in the extension popup.
The extension reads the stored WeRead user VID and sends it to weread.qnmlgb.tech/submit.
- Stored WeRead user VID1234567890 (illustrative)
A stored account identifier can link the popup submission to the logged-in WeRead user.
What it can do
Permissions this extension asks for, as declared in version 0.0.27. 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 i.weread.qq.com
*://i.weread.qq.com/*
Read and change your data on weread.qq.com
*://weread.qq.com/*
Read and change your data on r.qq.com
*://r.qq.com/*
Read and change your data on qnmlgb.tech
*://*.qnmlgb.tech/*
Read and change your data on file.myqcloud.com
*://*.file.myqcloud.com/*
Store data in your browser
storage
Read and change cookies, including the ones that keep you signed in
cookies
Speak text aloud
tts
Watch every request your browser makes
webRequest
Watch, block and rewrite every request your browser makes
webRequestBlocking