Files
overleaf-cep/.yarn/patches/@node-saml-passport-saml-npm-5.1.0-5d7df575fa.patch
Jakob Ackermann 6ca58edf72 [web] add infrastructure level zod change (#36190)
* [web] add infrastructure level zod change

* [web] set req validation mode for tests to 'enforce'

GitOrigin-RevId: 6dbc8bff7ed9f89045c398df93d84bca589de4e9
2026-09-17 11:48:19 +00:00

100 lines
6.5 KiB
Diff

diff --git a/lib/strategy.js b/lib/strategy.js
index 4de162f7e92a20b1ccd4d34dd9bcc0916f4c8c43..c67bb4e0b0287d615eac4c01b84c83d2bac91446 100644
--- a/lib/strategy.js
+++ b/lib/strategy.js
@@ -5,6 +5,29 @@ const passport_strategy_1 = require("passport-strategy");
const assert_1 = require("assert");
const url = require("url");
const node_saml_1 = require("@node-saml/node-saml");
+// --- Overleaf patch: request-input lockdown compatibility ---
+// This library reads req.query/req.body directly to parse the SAML protocol
+// fields (SAMLResponse, SAMLRequest, RelayState) it's built around, which is
+// otherwise indistinguishable from unvalidated application code reading raw
+// request input under Overleaf's request-input lockdown (see
+// libraries/validation-tools and the patched express in
+// .yarn/patches/express-npm-*.patch). The lockdown captures the original
+// parsed values in symbol-keyed fields, registered in the global symbol
+// registry (the same ones @overleaf/validation-tools' lockdown.js reads), and
+// only turns the *public* req.query/req.body properties into throwing
+// accessors -- reading through these raw fields instead sidesteps that, and
+// is identical to plain req.query/req.body when the lockdown isn't installed
+// (i.e. for every consumer of this package outside this monorepo).
+const __overleafLockdownInstalled = Symbol.for("overleaf.lockdown.installed");
+const __overleafLockdownRawQuery = Symbol.for("overleaf.lockdown.rawQuery");
+const __overleafLockdownRawBody = Symbol.for("overleaf.lockdown.rawBody");
+function __overleafRawQuery(req) {
+ return req[__overleafLockdownInstalled] ? req[__overleafLockdownRawQuery] : req.query;
+}
+function __overleafRawBody(req) {
+ return req[__overleafLockdownInstalled] ? req[__overleafLockdownRawBody] : req.body;
+}
+// --- end Overleaf patch ---
class AbstractStrategy extends passport_strategy_1.Strategy {
constructor(options, signonVerify, logoutVerify) {
super();
@@ -52,7 +75,7 @@ class AbstractStrategy extends passport_strategy_1.Strategy {
catch (_c) {
userMatch = false;
}
- const RelayState = ((_a = req.query) === null || _a === void 0 ? void 0 : _a.RelayState) || ((_b = req.body) === null || _b === void 0 ? void 0 : _b.RelayState);
+ const RelayState = ((_a = __overleafRawQuery(req)) === null || _a === void 0 ? void 0 : _a.RelayState) || ((_b = __overleafRawBody(req)) === null || _b === void 0 ? void 0 : _b.RelayState);
if (this._saml == null) {
return this.error(new Error("Can't get logout response URL without a SAML provider defined."));
}
@@ -125,22 +148,22 @@ class AbstractStrategy extends passport_strategy_1.Strategy {
this.redirect(url);
}
};
- if (((_a = req.query) === null || _a === void 0 ? void 0 : _a.SAMLResponse) || ((_b = req.query) === null || _b === void 0 ? void 0 : _b.SAMLRequest)) {
+ if (((_a = __overleafRawQuery(req)) === null || _a === void 0 ? void 0 : _a.SAMLResponse) || ((_b = __overleafRawQuery(req)) === null || _b === void 0 ? void 0 : _b.SAMLRequest)) {
const originalQuery = (_c = url.parse(req.url).query) !== null && _c !== void 0 ? _c : "";
this._saml
- .validateRedirectAsync(req.query, originalQuery)
+ .validateRedirectAsync(__overleafRawQuery(req), originalQuery)
.then(validateCallback)
.catch((err) => this.error(err));
}
- else if ((_d = req.body) === null || _d === void 0 ? void 0 : _d.SAMLResponse) {
+ else if ((_d = __overleafRawBody(req)) === null || _d === void 0 ? void 0 : _d.SAMLResponse) {
this._saml
- .validatePostResponseAsync(req.body)
+ .validatePostResponseAsync(__overleafRawBody(req))
.then(validateCallback)
.catch((err) => this.error(err));
}
- else if ((_e = req.body) === null || _e === void 0 ? void 0 : _e.SAMLRequest) {
+ else if ((_e = __overleafRawBody(req)) === null || _e === void 0 ? void 0 : _e.SAMLRequest) {
this._saml
- .validatePostRequestAsync(req.body)
+ .validatePostRequestAsync(__overleafRawBody(req))
.then(validateCallback)
.catch((err) => this.error(err));
}
@@ -151,7 +174,7 @@ class AbstractStrategy extends passport_strategy_1.Strategy {
if (this._saml == null) {
throw new Error("Can't process login request without a SAML provider defined.");
}
- const RelayState = (req.query && req.query.RelayState) || (req.body && req.body.RelayState);
+ const RelayState = (__overleafRawQuery(req) && __overleafRawQuery(req).RelayState) || (__overleafRawBody(req) && __overleafRawBody(req).RelayState);
const host = req.headers && req.headers.host;
if (this._saml.options.authnRequestBinding === "HTTP-POST") {
const data = await this._saml.getAuthorizeFormAsync(RelayState, host);
@@ -172,7 +195,7 @@ class AbstractStrategy extends passport_strategy_1.Strategy {
throw new Error("Can't process logout request without a SAML provider defined.");
}
try {
- const RelayState = (req.query && req.query.RelayState) || (req.body && req.body.RelayState);
+ const RelayState = (__overleafRawQuery(req) && __overleafRawQuery(req).RelayState) || (__overleafRawBody(req) && __overleafRawBody(req).RelayState);
// Defaults to HTTP-Redirect
this.redirect(await this._saml.getLogoutUrlAsync(req.user, RelayState, options));
}
@@ -188,7 +211,7 @@ class AbstractStrategy extends passport_strategy_1.Strategy {
if (this._saml == null) {
throw new Error("Can't logout without a SAML provider defined.");
}
- const RelayState = (req.query && req.query.RelayState) || (req.body && req.body.RelayState);
+ const RelayState = (__overleafRawQuery(req) && __overleafRawQuery(req).RelayState) || (__overleafRawBody(req) && __overleafRawBody(req).RelayState);
this._saml
.getLogoutUrlAsync(req.user, RelayState, {})
.then((url) => callback(null, url))