VYPR
High severity7.1OSV Advisory· Published Sep 9, 2025· Updated Apr 15, 2026

CVE-2025-58765

CVE-2025-58765

Description

wabac.js provides a full web archive replay system, or 'wayback machine', using Service Workers. A Reflected Cross-Site Scripting (XSS) vulnerability exists in the 404 error handling logic of wabac.js v2.23.10 and below. The parameter requestURL (derived from the original request target) is directly embedded into an inline <script> block without sanitization or escaping. This allows an attacker to craft a malicious URL that executes arbitrary JavaScript in the victim’s browser. The scope may be limited by CORS policies, depending on the situation in which wabac.js is used. The vulnerability is fixed in wabac.js v2.23.11.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
@webrecorder/wabacnpm
< 2.23.112.23.11
replaywebpagenpm
< 2.3.172.3.17
@webrecorder/archivewebpagenpm
< 0.15.40.15.4

Affected products

1

Patches

2
0c59ee0081c8

deps: bump to warcio 2.4.5 (#276)

https://github.com/webrecorder/wabac.jsIlya KreymerSep 4, 2025via osv
2 files changed · +6 6
  • package.json+2 2 modified
    @@ -1,6 +1,6 @@
     {
       "name": "@webrecorder/wabac",
    -  "version": "2.23.10",
    +  "version": "2.23.11",
       "main": "index.js",
       "type": "module",
       "exports": {
    @@ -37,7 +37,7 @@
         "path-parser": "^6.1.0",
         "process": "^0.11.10",
         "stream-browserify": "^3.0.0",
    -    "warcio": "^2.4.3"
    +    "warcio": "^2.4.5"
       },
       "devDependencies": {
         "@swc-node/register": "^1.10.9",
    
  • yarn.lock+4 4 modified
    @@ -3736,10 +3736,10 @@ warcio@^2.4.0:
         uuid-random "^1.3.2"
         yargs "^17.7.2"
     
    -warcio@^2.4.3:
    -  version "2.4.3"
    -  resolved "https://registry.yarnpkg.com/warcio/-/warcio-2.4.3.tgz#37ff95c2358d0d5ddb16e924fe200c4774b3903d"
    -  integrity sha512-c397HNfLE7yJsyVF3XKXB+Yh3q3WKljhdYRPkKF9eyZMtB+HIxj1aBqgq0nTYz492KMKtzygBo0Gx+Gi0fJ9dg==
    +warcio@^2.4.5:
    +  version "2.4.5"
    +  resolved "https://registry.yarnpkg.com/warcio/-/warcio-2.4.5.tgz#ba39c38e433491ab9016282813b9cf6539c3d808"
    +  integrity sha512-b6R/aIsR4fXzrpY/Zud7LqHFi2Bt8Ov5VLOnruHQ10rk129e9d0KOCZlyRmPD6ENTcV7yze5rXvJ5WSNS8R1zw==
       dependencies:
         "@types/pako" "^1.0.7"
         "@types/stream-buffers" "^3.0.7"
    
25feb4a5af69

Security: Reduce XSS attack surface for templated HTML (#275)

2 files changed · +119 90
  • src/collection.ts+1 1 modified
    @@ -191,7 +191,7 @@ export class Collection {
           if (await handleAuthNeeded(e, this.config)) {
             return notFound(
               request.request,
    -          '<p style="margin: auto">Please wait, this page will reload after authentication...</p>',
    +          "Please wait, this page will reload after authentication...",
               401,
             );
           }
    
  • src/notfound.ts+118 89 modified
    @@ -73,58 +73,72 @@ function getHTMLNotFound(
       liveRedirectOnNotFound: boolean,
       msg?: string,
     ) {
    -  return `
    -  <!doctype html>
    -  <html>
    -  <head>
    -  <script>
    -  window.requestURL = "${requestURL}";
    -  </script>
    -  </head>
    -  <body style="font-family: sans-serif">
    -  <h2>Archived Page Not Found</h2>
    -  <p>${msg || "Sorry, this page was not found in this archive:"}</p>
    -  <p><code id="url" style="word-break: break-all; font-size: larger"></code></p>
    -  ${
    -    liveRedirectOnNotFound && request.mode === "navigate"
    -      ? `
    -  <p>Redirecting to live page now... (If this URL is a file download, the download should have started).</p>
    -  <script>
    -  window.top.location.href = window.requestURL;
    -  </script>
    -  `
    -      : `
    -  `
    -  }
    -  <p id="goback" style="display: none"><a href="#" onclick="window.history.back()">Go Back</a> to the previous page.</a></p>
    -  
    -  <p>
    -  <a id="livelink" target="_blank" href="">Load the live page</a> in a new tab (or download the file, if this URL points to a file).
    -  </p>
    -
    -  <script>
    -  document.querySelector("#url").innerText = window.requestURL;
    -  document.querySelector("#livelink").href = window.requestURL;
    -  let isTop = true;
    -  try {
    -    if (window.parent._WB_wombat_location) {
    -      isTop = false;
    -    }
    -  } catch (e) {
    -
    -  }
    -  if (isTop) {
    -    document.querySelector("#goback").style.display = "";
    -
    -    window.parent.postMessage({
    -      wb_type: "archive-not-found",
    -      url: window.requestURL,
    -      ts: "${requestTS}"
    -    }, "*");
    -  }
    -  </script>
    -  </body>
    -  </html>
    +  return /* HTML */ `
    +    <!doctype html>
    +    <html>
    +      <head>
    +        <script>
    +          window.requestURL = ${JSON.stringify(requestURL)};
    +        </script>
    +      </head>
    +      <body style="font-family: sans-serif">
    +        <h2>Archived Page Not Found</h2>
    +        <p id="msg"></p>
    +        <p>
    +          <code
    +            id="url"
    +            style="word-break: break-all; font-size: larger"
    +          ></code>
    +        </p>
    +        ${liveRedirectOnNotFound && request.mode === "navigate"
    +          ? /* HTML */ `
    +              <p>
    +                Redirecting to live page now... (If this URL is a file download,
    +                the download should have started).
    +              </p>
    +              <script>
    +                window.top.location.href = window.requestURL;
    +              </script>
    +            `
    +          : `
    +  `}
    +        <p id="goback" style="display: none">
    +          <a href="#" onclick="window.history.back()">Go Back</a> to the
    +          previous page.
    +        </p>
    +
    +        <p>
    +          <a id="livelink" target="_blank" href="">Load the live page</a> in a
    +          new tab (or download the file, if this URL points to a file).
    +        </p>
    +
    +        <script>
    +          document.querySelector("#url").innerText = window.requestURL;
    +          document.querySelector("#msg").innerText = ${JSON.stringify(
    +            msg || "Sorry, this page was not found in this archive:",
    +          )};
    +          document.querySelector("#livelink").href = window.requestURL;
    +          let isTop = true;
    +          try {
    +            if (window.parent._WB_wombat_location) {
    +              isTop = false;
    +            }
    +          } catch (e) {}
    +          if (isTop) {
    +            document.querySelector("#goback").style.display = "";
    +
    +            window.parent.postMessage(
    +              {
    +                wb_type: "archive-not-found",
    +                url: window.requestURL,
    +                ts: ${JSON.stringify(requestTS)},
    +              },
    +              "*",
    +            );
    +          }
    +        </script>
    +      </body>
    +    </html>
       `;
     }
     
    @@ -135,8 +149,8 @@ function getScriptCSSNotFound(
       msg?: string,
     ) {
       return `\
    -/* 
    -   ${msg ? msg : type + " Not Found"}
    +/*
    +   ${msg || type + " Not Found"}
        URL: ${requestURL}
        TS: ${requestTS}
     */
    @@ -152,40 +166,55 @@ export function getProxyNotFoundResponse(url: string, status: number) {
     }
     
     function getHTMLNotProxyError(requestURL: string, status: number) {
    -  return `
    -  <!doctype html>
    -  <html>
    -  <head>
    -  <script>
    -  window.requestURL = "${requestURL}";
    -  </script>
    -  </head>
    -  <body style="font-family: sans-serif">
    -  <h2>Live page could not be loaded</h2>
    -  <p>Sorry, this page was could not be loaded through the archiving proxy. Check the URL and try again.</p>
    -  <p><code id="url" style="word-break: break-all; font-size: larger">Status Code: ${status}</code></p>
    -  <p id="goback" style="display: none"><a href="#" onclick="window.history.back()">Go Back</a> to the previous page.</a></p>
    -
    -  <script>
    -  let isTop = true;
    -  try {
    -    if (window.parent._WB_wombat_location) {
    -      isTop = false;
    -    }
    -  } catch (e) {
    -
    -  }
    -  if (isTop) {
    -    document.querySelector("#goback").style.display = "";
    -
    -    window.parent.postMessage({
    -      wb_type: "live-proxy-url-error",
    -      url: window.requestURL,
    -      status: ${status},
    -    }, "*");
    -  }
    -  </script>
    -  </body>
    -  </html>
    +  return /* HTML */ `
    +    <!doctype html>
    +    <html>
    +      <head>
    +        <script>
    +          window.requestURL = ${JSON.stringify(requestURL)};
    +        </script>
    +      </head>
    +      <body style="font-family: sans-serif">
    +        <h2>Live page could not be loaded</h2>
    +        <p>
    +          Sorry, this page was could not be loaded through the archiving proxy.
    +          Check the URL and try again.
    +        </p>
    +        <p>
    +          <code
    +            id="url"
    +            style="word-break: break-all; font-size: larger"
    +          ></code>
    +        </p>
    +        <p id="goback" style="display: none">
    +          <a href="#" onclick="window.history.back()">Go Back</a> to the
    +          previous page.
    +        </p>
    +
    +        <script>
    +          document.getElementById("url").innerText = ${JSON.stringify(
    +            `Status Code: ${status}`,
    +          )};
    +          let isTop = true;
    +          try {
    +            if (window.parent._WB_wombat_location) {
    +              isTop = false;
    +            }
    +          } catch (e) {}
    +          if (isTop) {
    +            document.querySelector("#goback").style.display = "";
    +
    +            window.parent.postMessage(
    +              {
    +                wb_type: "live-proxy-url-error",
    +                url: window.requestURL,
    +                status: ${JSON.stringify(status)},
    +              },
    +              "*",
    +            );
    +          }
    +        </script>
    +      </body>
    +    </html>
       `;
     }
    

Vulnerability mechanics

Synthesis attempt was rejected by the grounding validator. Re-run pending.

References

8

News mentions

0

No linked articles in our index yet.