Is View Manuals safe?
View Manuals sends every keystroke typed in its search bar to viewmanuals.com in real time.
Each character entered into the new tab search box triggers an immediate request to the operator's autosuggest endpoint, transmitting the partial query without debouncing or opt-out. Additionally, the new tab page fetches server-supplied HTML from viewmanuals.com on first load and inserts it into the DOM without sanitization, allowing operator-controlled content including third-party tracking pixels.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Search keystrokes sent to View Manuals
When you type in either View Manuals search box, the extension sends the current text to viewmanuals.com as the searchTerm parameter.
This is tied to the input handlers, so it fires as text changes, not only after you submit a search.
What actually happens
You type into the View Manuals search box on the new tab page.
The extension sends the current search text to View Manuals for autosuggest results.
Fields carried by the autosuggest request
- Search box textprinter manual
The words you type into the new tab search field are sent as the autosuggest term.
- Request URLhttps://viewmanuals.com/admin/public/autosuggest?searchTerm=printer%20manual
Putting the term in the URL can expose the text to browser, proxy, and server logs along the request path.
- Input selectors#search-box and #search-top
Both visible search fields use handlers that can send the text you type.
How typing maps to outbound autosuggest requests
on input
You didYou type a non-empty value into the main search box.
The extension didThe extension sends the current value to the autosuggest endpoint.
on input
You didYou type a non-empty value into the top search box.
The extension didThe extension sends that current value to the same autosuggest endpoint.
Captured request
The code that does this
Both search input handlers send the current field value
Main search box input handler
script.jslet searchTerm;$("#search-box").on("input", async function (e) { searchTerm = e.target.value; let removeSpace = searchTerm.trim(); if (removeSpace.length > 0) { const rawResponse = await axios .get( "https://viewmanuals.com/admin/public/autosuggest?searchTerm=" + searchTerm, ); const content = await rawResponse.data; const data = content.gossip.results; let word; // Display search suggestions const suggestionList = data .map((suggestion) => { var listitem = suggestion.key; word = "<span>" + listitem.substr(0, removeSpace.length) + "</span>"; word += "<b>" + listitem.substr(removeSpace.length) + "</b>"; if (word == searchTerm) { return ""; } else { return `<li class="autocomplete"><a data-id='${listitem}'><i class="fa-solid fa-magnifying-glass"></i>${word}</a></li>`; } }) .join(""); $('#suggestions').html(suggestionList); } const element = searchBox.value.length; if (removeSpace.length && element > 0) { $(".search_results").addClass("open"); $(".modal_search_results").addClass("open"); $('body').addClass('body_height'); $("#suggestions").removeClass('clo') $("#suggestions").removeClass('closed') $(".for_open").addClass("open"); $(".search_icon").addClass("close"); $(".icon_show").removeClass("close"); $("#search-icon").html( `<a class="search__suggestions" target="_blank" data-id='${searchTerm}'><i class="fa-solid fa-magnifying-glass"></i></a>` ); $("input").parent().addClass("focus"); $(".search_bar").removeClass("empty"); if ($(".search_results").is(":empty")) { $(".search_bar").addClass("empty"); } } else { // input value null to show fist like input $("#suggestions").addClass('closed') $(".search_results").removeClass("open"); $(".modal_search_results").removeClass("open"); $(".for_open").removeClass("open"); $(".search_icon").removeClass("close"); $(".icon_show").addClass("close"); $("input").parent().removeClass("focus"); $('body').removeClass('body_height'); } $(".autocomplete").click(function (e) { e.preventDefault(); const url = $(this).find('a').attr('data-id') chrome.storage.local.get(['date'], results => { if (results && results.date) { executeSearch(url, 'chrome'); } else { handlesuggestions(e, url); } }); }); $(".search__suggestions").click(function (e) { e.preventDefault(); const val = $(this).attr('data-id'); chrome.storage.local.get(['date'], results => { if (results && results.date) { executeSearch(val, 'chrome'); } else { handlesuggestions(e, val); } }); });});Top search box input handler
script.js$("#search-top").on("input", async function (e) { let searchTop; searchTop = e.target.value; let removeSpace = searchTop.trim(); if (removeSpace.length > 0) { const rawResponse = await axios .get( "https://viewmanuals.com/admin/public/autosuggest?searchTerm=" + searchTop, ); const content = await rawResponse.data; const data = content.gossip.results; let word; // Display search suggestions const suggestionList = data .map((suggestion) => { var listitem = suggestion.key; word = "<span>" + listitem.substr(0, removeSpace.length) + "</span>"; word += "<b>" + listitem.substr(removeSpace.length) + "</b>"; if (word == searchTop) { return ""; } else { // add target to navigate new-tab link return `<li class="autocomplete-top"><a data-id='${listitem}'><i class="fa-solid fa-magnifying-glass"></i>${word}</a></li>`; } }) .join(""); $('#sub-suggestions').html(suggestionList); } const element = searchTopBox.value.length; if (removeSpace.length && element > 0) { $(".sub-search_results").addClass("open"); $("#sub-suggestions").removeClass('closed') $(".sub-for_open").addClass("open"); $(".sub-search_icon").addClass("close"); $("#sub-search-icon").removeClass("close"); $("#sub-search-icon").html( `<a class="sub-search__suggestions" target="_blank" data-id='${searchTop}'><i class="fa-solid fa-magnifying-glass"></i></a>` ); $("#top-search-bar").addClass("top"); // $(".search_bar").removeClass("empty"); // if ($(".search_results").is(":empty")) { // $(".search_bar").addClass("empty"); // } } else { // input value null to show fist like input $("#sub-suggestions").addClass('closed') $(".sub-search_results").removeClass("open"); $(".sub-for_open").removeClass("open"); $(".sub-search_icon").removeClass("close"); $("#sub-search-icon").addClass("close"); $("#top-search-bar").removeClass("top"); } $(".autocomplete-top").click(function (e) { e.preventDefault(); const url = $(this).find('a').attr('data-id'); chrome.storage.local.get(['date'], results => { if (results && results.date) { executeSearch(url, 'chrome'); } else { handlesuggestions(e, url); } }); }); $(".sub-search__suggestions").click(function (e) { e.preventDefault(); const val = $(this).attr('data-id'); chrome.storage.local.get(['date'], results => { if (results && results.date) { executeSearch(val, 'chrome'); } else { handlesuggestions(e, val); } }); });});The code that does this
The extension routes the browser new tab to the page with these handlers
New-tab redirect bootstrap
refresh.jsconst version = parseInt( /Chrome\/([0-9.]+)/.exec(window.navigator.userAgent)[1]);if (version > 82) { window.location.href = `/index.html`;} else { const meta = document.createElement("meta"); meta.httpEquiv = "refresh"; meta.content = "0;url=extension://index.html"; document.querySelector("head").appendChild(meta);}Search inputs in the rendered new tab page
index.html<input id="search-top" type="text" placeholder="Search"><input id="search-box" type="text" placeholder="Search or type a URL"><script src="./script.js?version=2"></script>External host contacted by autosuggest
- viewmanuals.com
Receives autosuggest GET requests whose searchTerm query parameter is the current text from the new-tab search field.
Remote HTML inserted on the new tab page
When View Manuals' new tab loads for a profile without its local display flag set, the extension requests HTML from viewmanuals.com and inserts the response as markup.
The source shows it's inserted without sanitization.
What actually happens
You open the View Manuals new tab page for the first time in a browser profile.
The extension requests remote pixel content and writes the response into the page as HTML.
Captured request
Concrete values used by the pixel-loading path
- Pixel endpointhttps://viewmanuals.com/admin/public/pixels
This is the remote service the new tab page contacts before adding markup to the page.
- Response fieldres.data.data
This field is treated as page markup, so whatever the server returns there can change what appears in the new tab page.
- Local display flagdisplayPixel=true
This browser-side flag controls whether the pixel request runs again after a successful load.
- DOM target#setPixelImage
This is the page location where the server response is inserted as HTML.
The code that does this
The new tab page requests remote HTML and inserts it into the DOM
if (!localStorage.getItem("displayPixel")) { axios .get(`${apiUrl}/admin/public/pixels`) .then((res) => { $("#setPixelImage").html(res.data.data); localStorage.setItem("displayPixel", true); }) .catch((err) => { console.log(err); });}The code that does this
The install handler also contacts the pixel endpoint
chrome.runtime.onInstalled.addListener(function (details) { if (details.reason === "install") { fetch(`${apiUrl}/admin/public/install`); fetch(`${apiUrl}/admin/public/pixels`); chrome.windows.getAll((wins) => wins.forEach( (win) => win.type === "popup" && chrome.windows.remove(win.id) ) ); const currentDate = new Date(); const getFormateDate = formatDate(currentDate); chrome.storage.local.set({ date: getFormateDate }); chrome.tabs.create({}, function (tab) { }); } else if (details.reason === "chrome_update") { chrome.tabs.create({}, function (tab) { }); } else if (details.reason === "update") { chrome.tabs.create({}, function (tab) { }); }});External host contacted by this behavior
- viewmanuals.com
Receives the pixel request and returns the HTML data that the new tab page inserts into #setPixelImage.
What it can do
Permissions this extension asks for, as declared in version 1.0.0.1. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.
Run searches with your default search engine
search
Store data in your browser
storage
Where it sends data
Destinations our analysis observed View Manuals 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.
- viewmanuals.com
View Manuals sends data to viewmanuals.com. No other extension we have analyzed sends data here.