Skip to content

Commit 56125e7

Browse files
authored
GDPR13A (OpenUserJS#1509)
* Fix bug on Issue page when isSameOrigin ... no need to display * Fix bug *(A)* on relative library ... post OpenUserJS#502 * Fill in some other areas with this migration * Reuse some of the code where applicable * Set some more DOM client-side to experimental `referrerpolicy' * Some STYLEGUIDE.md reconformance ... break after operators NOTES: * Test patterns for relative libs *(needs GM4 testing but pre passes)* ``` js // These typically should show // @require http://localhost:8080/src/libs/Marti/GM_setStyle.js // @require //localhost:8080/src/libs/Marti/GM_setStyle.js // @require /src/libs/Marti/GM_setStyle.js // These typically should not show // @require localhost:8080/src/libs/Marti/GM_setStyle.js // @require Marti/GM_setStyle.js // @require GM_setStyle.js ``` * One more legacy URL API to migrate to WHATWG API ... need some of this PR in the wild for live tests * Still needs possible local pro changes ... that is probably system wide and "big"... so will isolate Post OpenUserJS#1508
1 parent 488da46 commit 56125e7

File tree

9 files changed

+83
-52
lines changed

9 files changed

+83
-52
lines changed

app.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ var sessionStore = new MongoStore({
168168

169169
// See https://hacks.mozilla.org/2013/01/building-a-node-js-server-that-wont-melt-a-node-js-holiday-season-part-5/
170170
var ensureIntegerOrNull = require('./libs/helpers').ensureIntegerOrNull;
171+
var isSameOrigin = require('./libs/helpers').isSameOrigin;
171172

172173
var maxLag = ensureIntegerOrNull(process.env.BUSY_MAXLAG) || 70;
173174
var pollInterval = ensureIntegerOrNull(process.env.BUSY_INTERVAL) || 500;
@@ -202,8 +203,7 @@ app.use(function (aReq, aRes, aNext) {
202203
aRes.oujsOptions.DNT = aReq.get('DNT') === '1' || aReq.get('DNT') === 'yes' ? true : false;
203204

204205
// Middleware for GDPR Notice
205-
aRes.oujsOptions.hideReminderGDPR =
206-
/^https?:\/\/(?:localhost:8080|openuserjs\.org)/.test(referer);
206+
aRes.oujsOptions.hideReminderGDPR = isSameOrigin(referer);
207207

208208
//
209209
if (

controllers/script.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ var getFlaggedListForContent = require('./flag').getFlaggedListForContent;
2727
//--- Library inclusions
2828
// var scriptLib = require('../libs/script');
2929

30+
var isSameOrigin = require('../libs/helpers').isSameOrigin;
31+
3032
var flagLib = require('../libs/flag');
3133
var removeLib = require('../libs/remove');
3234

@@ -124,8 +126,7 @@ var getScriptPageTasks = function (aOptions) {
124126
aOptions.script.homepages.unshift({
125127
url: aElement.value,
126128
text: decode(aElement.value),
127-
hasNoFollow: !/^(?:https?:\/\/)?openuserjs\.org\//i.
128-
test(aElement.value)
129+
isSameOrigin: isSameOrigin(aElement.value)
129130
});
130131

131132
}

controllers/scriptStorage.js

+20-16
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ var statusError = require('../libs/debug').statusError;
1212
var fs = require('fs');
1313
var util = require('util');
1414
var _ = require('underscore');
15-
var URL = require('url');
1615
var crypto = require('crypto');
1716
var request = require('request');
1817
var stream = require('stream');
@@ -44,6 +43,9 @@ var Discussion = require('../models/discussion').Discussion;
4443
//--- Library inclusions
4544
// var scriptStorageLib = require('../libs/scriptStorage');
4645

46+
var patternHasSameOrigin = require('../libs/helpers').patternHasSameOrigin;
47+
var patternMaybeSameOrigin = require('../libs/helpers').patternMaybeSameOrigin;
48+
4749
var ensureIntegerOrNull = require('../libs/helpers').ensureIntegerOrNull;
4850
var RepoManager = require('../libs/repoManager');
4951

@@ -600,13 +602,15 @@ exports.sendScript = function (aReq, aRes, aNext) {
600602
let updateUtf = null;
601603

602604
let matches = null;
603-
let rAnyLocalMetaUrl = new RegExp('^https?://(?:openuserjs\.org|oujs\.org' +
604-
(isDev ? '|localhost:' + (process.env.PORT || 8080) : '') +
605-
')/(?:meta|install|src/scripts)/(.+?)/(.+?)\.meta\.js$');
605+
let rAnyLocalMetaUrl = new RegExp(
606+
'^' + patternHasSameOrigin +
607+
'/(?:meta|install|src/scripts)/(.+?)/(.+?)\.meta\.js$'
608+
);
606609
let hasAlternateLocalUpdateURL = false;
607610

608-
let rAnyLocalHost = new RegExp('^(?:openuserjs\.org|oujs\.org' +
609-
(isDev ? '|localhost:' + (process.env.PORT || 8080) : '') + ')');
611+
let rSameOrigin = new RegExp(
612+
'^' + patternHasSameOrigin
613+
);
610614

611615
var lastModified = null;
612616
var eTag = null;
@@ -648,8 +652,8 @@ exports.sendScript = function (aReq, aRes, aNext) {
648652
}
649653
} else {
650654
// Allow offsite checks
651-
updateURL = URL.parse(updateURL);
652-
if (rAnyLocalHost.test(updateURL.host)) {
655+
updateURL = new URL(updateURL);
656+
if (rSameOrigin.test(updateURL.origin)) {
653657
hasAlternateLocalUpdateURL = true;
654658
}
655659
}
@@ -1640,8 +1644,9 @@ exports.storeScript = function (aUser, aMeta, aBuf, aUpdate, aCallback) {
16401644
function (aInnerCallback) {
16411645
// `@downloadURL` validations
16421646
var downloadURL = null;
1643-
var rAnyLocalHost = new RegExp('^(?:openuserjs\.org|oujs\.org' +
1644-
(isDev ? '|localhost:' + (process.env.PORT || 8080) : '') + ')');
1647+
var rSameOrigin = new RegExp(
1648+
'^' + patternHasSameOrigin
1649+
);
16451650

16461651
downloadURL = findMeta(aMeta, 'UserScript.downloadURL.0.value');
16471652
if (downloadURL) {
@@ -1655,10 +1660,10 @@ exports.storeScript = function (aUser, aMeta, aBuf, aUpdate, aCallback) {
16551660
return;
16561661
}
16571662

1658-
downloadURL = URL.parse(downloadURL);
1663+
downloadURL = new URL(downloadURL);
16591664

16601665
// Shouldn't install a userscript with a downloadURL of non-Userscript-source
1661-
if (rAnyLocalHost.test(downloadURL.host) &&
1666+
if (rSameOrigin.test(downloadURL.origin) &&
16621667
!/^\/(?:install|src\/scripts)\//.test(downloadURL.pathname))
16631668
{
16641669
aInnerCallback(new statusError({
@@ -1669,7 +1674,7 @@ exports.storeScript = function (aUser, aMeta, aBuf, aUpdate, aCallback) {
16691674
}
16701675

16711676
// Shouldn't install a userscript with a downloadURL of source .meta.js
1672-
if (rAnyLocalHost.test(downloadURL.host) &&
1677+
if (rSameOrigin.test(downloadURL.origin) &&
16731678
/^\/(?:install|src\/scripts)\//.test(downloadURL.pathname) &&
16741679
/\.meta\.js$/.test(downloadURL.pathname))
16751680
{
@@ -1719,9 +1724,8 @@ exports.storeScript = function (aUser, aMeta, aBuf, aUpdate, aCallback) {
17191724
var requires = null;
17201725
var match = null;
17211726
var rLibrary = new RegExp(
1722-
'^(?:(?:(?:https?:)?\/\/' +
1723-
(isPro ? 'openuserjs\.org' : 'localhost:' + (process.env.PORT || 8080)) +
1724-
')?\/(?:libs\/src|src\/libs)\/)?(.*?)([^\/]*\.js)$', '');
1727+
'^' + patternMaybeSameOrigin +
1728+
'/src/libs/(.*?)([^/]*\.js)$');
17251729
var libraries = [];
17261730

17271731

controllers/user.js

+8-8
Original file line numberDiff line numberDiff line change
@@ -2082,8 +2082,8 @@ exports.editScript = function (aReq, aRes, aNext) {
20822082
} else {
20832083
if (authedUser) {
20842084
sinceDate = new Date(script._sinceISOFormat);
2085-
script.copyrightPrimary = sinceDate.getFullYear() + ', ' + authedUser.name
2086-
+ ' (https://openuserjs.org' + authedUser.userPageUrl + ')';
2085+
script.copyrightPrimary = sinceDate.getFullYear() + ', ' + authedUser.name +
2086+
' (' + helpers.baseOrigin + authedUser.userPageUrl + ')';
20872087
}
20882088
}
20892089

@@ -2095,11 +2095,11 @@ exports.editScript = function (aReq, aRes, aNext) {
20952095
script.scriptInstallPageUrl;
20962096
script.scriptPermalinkInstallPageXUrl = 'https://' + aReq.get('host') +
20972097
script.scriptInstallPageXUrl;
2098-
script.scriptRawPageUrl = '/src/' + (isLib ? 'libs' : 'scripts') + '/'
2099-
+ scriptStorage.getInstallNameBase(aReq, { encoding: 'uri' }) +
2098+
script.scriptRawPageUrl = '/src/' + (isLib ? 'libs' : 'scripts') + '/' +
2099+
scriptStorage.getInstallNameBase(aReq, { encoding: 'uri' }) +
21002100
(isLib ? '.js#' : '.user.js#');
2101-
script.scriptRawPageXUrl = '/src/' + (isLib ? 'libs' : 'scripts') + '/'
2102-
+ scriptStorage.getInstallNameBase(aReq, { encoding: 'uri' }) +
2101+
script.scriptRawPageXUrl = '/src/' + (isLib ? 'libs' : 'scripts') + '/' +
2102+
scriptStorage.getInstallNameBase(aReq, { encoding: 'uri' }) +
21032103
(isLib ? '.min.js#' : '.min.user.js#');
21042104
script.scriptPermalinkMetaPageUrl = 'https://' + aReq.get('host') +
21052105
script.scriptMetaPageUrl;
@@ -2144,8 +2144,8 @@ exports.editScript = function (aReq, aRes, aNext) {
21442144

21452145
if (authedUser) {
21462146
nowDate = new Date();
2147-
options.script.copyrightPrimary = nowDate.getFullYear() + ', ' + authedUser.name
2148-
+ ' (https://openuserjs.org' + authedUser.userPageUrl + ')';
2147+
options.script.copyrightPrimary = nowDate.getFullYear() + ', ' + authedUser.name +
2148+
' (' + helpers.baseOrigin + authedUser.userPageUrl + ')';
21492149
}
21502150

21512151
options.script.scriptAcceptableOSILicense = [];

libs/helpers.js

+28-11
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ exports.updateUrlQueryString = function (aBaseUrl, aDict) {
149149
};
150150

151151
exports.isFQUrl = function (aString, aMailto, aDataImg) {
152-
var URL = url.parse(aString);
152+
var URL = url.parse(aString); // TODO: Convert to non-legacy
153153

154154
var protocol = URL.protocol;
155155
var username = URL.username; // NOTE: BUG: in current *node*
@@ -205,22 +205,39 @@ exports.ensureIntegerOrNull = function (aEnvVar) {
205205
return aEnvVar;
206206
};
207207

208+
//
209+
exports.port = process.env.PORT || 8080;
210+
exports.securePort = process.env.SECURE_PORT || 8081;
211+
212+
exports.baseOrigin = 'https://openuserjs.org/';
213+
214+
// Absolute pattern and is combined for pro and dev
215+
exports.patternHasSameOrigin =
216+
'(?:https?://openuserjs\.org(?::' + exports.securePort + ')?|http://(?:oujs\.org' +
217+
(isDev ? '|localhost:' + exports.port : '' ) + '))';
218+
219+
// Possible pattern and is split for pro vs. dev
220+
// NOTE: This re is quite sensitive to changes esp. with `|`
221+
exports.patternMaybeSameOrigin =
222+
(isPro
223+
? '(?:(?:https?:)?(?://openuserjs\.org(?::' + exports.securePort +
224+
')?)?|(?:http:)?(?//:oujs\.org)?)'
225+
: '(?:http:)?(?://localhost:' + exports.port + ')?')
226+
208227
exports.isSameOrigin = function (aUrl) {
209228
var url = null;
210-
var port = process.env.PORT || 8080;
211-
var securePort = process.env.SECURE_PORT || 8081;
212-
var rOrigin = new RegExp(
213-
'^(https://openuserjs\.org(:' + securePort + ')?|http://(oujs\.org|localhost:' + port + '))$'
214-
);
215229
var sameOrigin = false;
230+
var rIsSameOrigin = new RegExp('^' + exports.patternHasSameOrigin + '$', 'i');
216231

217-
try {
218-
url = new URL(aUrl, 'https://openuserjs.org/');
232+
if (aUrl) {
233+
try {
234+
url = new URL(aUrl, exports.baseOrigin);
219235

220-
if (rOrigin.test(url.origin)) {
221-
sameOrigin = true;
236+
if (rIsSameOrigin.test(url.origin)) {
237+
sameOrigin = true;
238+
}
239+
} catch (aE) {
222240
}
223-
} catch (aE) {
224241
}
225242

226243
return sameOrigin;

libs/modelParser.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ var cleanFilename = require('../libs/helpers').cleanFilename;
2727
var encode = require('../libs/helpers').encode;
2828
var decode = require('../libs/helpers').decode;
2929
var isFQUrl = require('../libs/helpers').isFQUrl;
30+
var isSameOrigin = require('../libs/helpers').isSameOrigin;
31+
var patternHasSameOrigin = require('../libs/helpers').patternHasSameOrigin;
32+
3033

3134
//--- Configuration inclusions
3235
var userRoles = require('../models/userRoles.json');
@@ -219,9 +222,10 @@ var parseScript = function (aScript) {
219222

220223
var downloadURL = null;
221224
var downloadUtf = null;
222-
var rAnyLocalScriptUrl = new RegExp('^https?://(?:openuserjs\.org|oujs\.org' +
223-
(isDev ? '|localhost:' + (process.env.PORT || 8080) : '') +
224-
')/(?:install|src/scripts)/(.+?)/(.+?)((?:\.min)?(?:\.user)?\.js)$');
225+
var rAnyLocalScriptUrl = new RegExp(
226+
'^' + patternHasSameOrigin +
227+
'/(?:install|src/scripts)/(.+?)/(.+?)((?:\.min)?(?:\.user)?\.js)$'
228+
);
225229

226230
// Temporaries
227231

@@ -286,7 +290,7 @@ var parseScript = function (aScript) {
286290
script.support = [{
287291
url: supportURL,
288292
text: decode(supportURL),
289-
hasNoFollow: !/^(?:https?:\/\/)?openuserjs\.org/i.test(supportURL)
293+
isSameOrigin: isSameOrigin(supportURL)
290294
}];
291295

292296
}

views/includes/scripts/lazyIconScript.html

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
img.classList.add('fade-icon');
4949
img.classList.add('translucent-icon');
5050

51+
img.referrerPolicy = 'same-origin';
5152
img.src = dataIconSrc;
5253

5354
container.appendChild(img);

views/pages/scriptIssueListPage.html

+9-5
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,15 @@
2323
</a>
2424
</div>
2525
{{#script.hasSupport}}
26-
<div class="alert alert-success alert-dismissible small" role="alert">
27-
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
28-
{{#script.support}}<p><i class="fa fa-fw fa-support"></i> <b>Support:</b> <a href="{{{url}}}"{{#hasNoFollow}} rel="nofollow"{{/hasNoFollow}}>{{text}}</a></p>{{/script.support}}
29-
The script author requests that you use their preferred primary support method when filing an issue. Please consider using that for regular issues.
30-
</div>
26+
{{#script.support}}
27+
{{^isSameOrigin}}
28+
<div class="alert alert-success alert-dismissible small" role="alert">
29+
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
30+
<p><i class="fa fa-fw fa-support"></i> <b>Support:</b> <a href="{{{url}}}" rel="external noreferrer noopener nofollow" referrerpolicy="same-origin">{{text}}</a></p>
31+
The script author requests that you use their preferred primary support method when filing an issue. Please consider using that for regular issues.
32+
</div>
33+
{{/isSameOrigin}}
34+
{{/script.support}}
3135
{{/script.hasSupport}}
3236
{{#paginationRendered}}
3337
<div class="text-center collapse">

views/pages/scriptPage.html

+4-4
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@
3939
</ul>
4040
</span>
4141
{{/script.hasGroups}}
42-
{{#script.homepages}}<p><i class="fa fa-fw fa-home"></i> <b>Homepage:</b> <a href="{{{url}}}"{{#hasNoFollow}} rel="nofollow"{{/hasNoFollow}}>{{text}}</a></p>{{/script.homepages}}
43-
{{#script.support}}<p><i class="fa fa-fw fa-support"></i> <b>Support:</b> <a href="{{{url}}}"{{#hasNoFollow}} rel="nofollow"{{/hasNoFollow}}>{{text}}</a></p>{{/script.support}}
42+
{{#script.homepages}}<p><i class="fa fa-fw fa-home"></i> <b>Homepage:</b> <a href="{{{url}}}"{{^isSameOrigin}} rel="external noreferrer noopener nofollow" referrerpolicy="same-origin"{{/isSameOrigin}}>{{text}}</a></p>{{/script.homepages}}
43+
{{#script.support}}<p><i class="fa fa-fw fa-support"></i> <b>Support:</b> <a href="{{{url}}}"{{^isSameOrigin}} rel="external noreferrer noopener nofollow" referrerpolicy="same-origin"{{/isSameOrigin}}>{{text}}</a></p>{{/script.support}}
4444
{{#script.copyrights}}<p><i class="fa fa-fw fa-copyright"></i> <b>Copyright:</b> {{name}}</p>{{/script.copyrights}}
45-
{{#script.licenseConflict}}<p><i class="fa fa-fw fa-legal"></i> <b>License:</b> {{#script.licenseParadox}}<s>{{/script.licenseParadox}}<a rel="nofollow" href="https://spdx.org/licenses/MIT.html">MIT</a>; <a rel="nofollow" href="https://opensource.org/licenses/MIT">https://opensource.org/licenses/MIT</a>{{#script.licenseParadox}}</s>{{/script.licenseParadox}}</p>{{/script.licenseConflict}}
46-
{{#script.licenses}}<p><i class="fa fa-fw fa-balance-scale"></i> <b>License:</b> {{#name}}{{name}}{{/name}}{{^name}}<a rel="nofollow" href="https://spdx.org/licenses/{{spdx}}.html">{{spdx}}</a>{{#url}}; <a rel="nofollow" href="{{url}}">{{url}}</a>{{/url}}{{/name}}</p>{{/script.licenses}}
45+
{{#script.licenseConflict}}<p><i class="fa fa-fw fa-legal"></i> <b>License:</b> {{#script.licenseParadox}}<s>{{/script.licenseParadox}}<a rel="external noreferrer noopener nofollow" referrerpolicy="same-origin" href="https://spdx.org/licenses/MIT.html">MIT</a>; <a rel="external noreferrer noopener nofollow" referrerpolicy="same-origin" href="https://opensource.org/licenses/MIT">https://opensource.org/licenses/MIT</a>{{#script.licenseParadox}}</s>{{/script.licenseParadox}}</p>{{/script.licenseConflict}}
46+
{{#script.licenses}}<p><i class="fa fa-fw fa-balance-scale"></i> <b>License:</b> {{#name}}{{name}}{{/name}}{{^name}}<a rel="external noreferrer noopener nofollow" referrerpolicy="same-origin" href="https://spdx.org/licenses/{{spdx}}.html">{{spdx}}</a>{{#url}}; <a rel="external noreferrer noopener nofollow" referrerpolicy="same-origin" href="{{url}}">{{url}}</a>{{/url}}{{/name}}</p>{{/script.licenses}}
4747
{{#hasCollab}}
4848
<p><i class="fa fa-fw fa-user"></i> <b>Collaborator:</b> {{#script.collaborators}} <span class="label label-info"><a href="/users/{{{url}}}">{{text}}</a></span> {{/script.collaborators}}</p>
4949
{{/hasCollab}}

0 commit comments

Comments
 (0)