Merge pull request #1543 from sharelatex/as-fix-potential-angular-xss

Fix potential Angular XSS issues

GitOrigin-RevId: a18a609a25b29e910cb78e28a37398417cfe4842
This commit is contained in:
Alasdair Smith 2019-03-18 10:24:54 +00:00 committed by sharelatex
parent c704312c85
commit 41f75b5936
29 changed files with 111 additions and 128 deletions

View file

@ -1,7 +1,7 @@
mixin faq_search(headerText, headerClass)
- if(typeof(settings.algolia) != "undefined" && typeof(settings.algolia.indexes) != "undefined" && typeof(settings.algolia.indexes.wiki) != "undefined")
if headerText
div(class=headerClass) #{headerText}
div(class=headerClass, ng-non-bindable) #{headerText}
.wiki(ng-controller="SearchWikiController")
form.project-search.form-horizontal(role="search")
.form-group.has-feedback.has-feedback-left

View file

@ -15,32 +15,32 @@ mixin linkAdvisors(linkText, linkClass, track)
event-tracking-mb=mb
event-segmentation=mbSegmentation
)
| #{linkText ? linkText : 'advisor programme'}
span(ng-non-bindable) #{linkText ? linkText : 'advisor programme'}
mixin linkBenefits(linkText, linkClass)
a(href=(settings.siteUrl ? settings.siteUrl : '') + "/for/authors" class=linkClass ? linkClass : '')
a(href=(settings.siteUrl ? settings.siteUrl : '') + "/for/authors" class=linkClass ? linkClass : '', ng-non-bindable)
| #{linkText ? linkText : 'benefits'}
mixin linkBlog(linkText, linkClass, slug)
if slug
a(href=(settings.siteUrl ? settings.siteUrl : '') + "/blog/" + slug class=linkClass ? linkClass : '')
a(href=(settings.siteUrl ? settings.siteUrl : '') + "/blog/" + slug class=linkClass ? linkClass : '', ng-non-bindable)
| #{linkText ? linkText : 'blog'}
mixin linkContact(linkText, linkClass)
a(href=(settings.siteUrl ? settings.siteUrl : '') + "/contact" class=linkClass ? linkClass : '')
a(href=(settings.siteUrl ? settings.siteUrl : '') + "/contact" class=linkClass ? linkClass : '', ng-non-bindable)
| #{linkText ? linkText : 'contact'}
mixin linkDash(linkText, linkClass)
a(href="/project" class=linkClass ? linkClass : '')
a(href="/project" class=linkClass ? linkClass : '', ng-non-bindable)
| #{linkText ? linkText : 'project dashboard'}
mixin linkEducation(linkText, linkClass)
a(href=(settings.siteUrl ? settings.siteUrl : '') + "/for/edu" class=linkClass ? linkClass : '')
a(href=(settings.siteUrl ? settings.siteUrl : '') + "/for/edu" class=linkClass ? linkClass : '', ng-non-bindable)
| #{linkText ? linkText : 'teaching toolkit'}
mixin linkEmail(linkText, linkClass, email)
- var emailAddress = email ? email : 'contact'
a(href="mailto:" + emailAddress + "@overleaf.com" class=linkClass ? linkClass : '')
a(href="mailto:" + emailAddress + "@overleaf.com" class=linkClass ? linkClass : '', ng-non-bindable)
| #{linkText ? linkText : 'email'}
mixin linkInvite(linkText, linkClass, track)
@ -60,10 +60,10 @@ mixin linkInvite(linkText, linkClass, track)
event-tracking-mb=mb
event-segmentation=mbSegmentation
)
| #{linkText ? linkText : 'invite your friends'}
span(ng-non-bindable) #{linkText ? linkText : 'invite your friends'}
mixin linkPlansAndPricing(linkText, linkClass)
a(href="/user/subscription/plans" class=linkClass ? linkClass : '')
a(href="/user/subscription/plans" class=linkClass ? linkClass : '', ng-non-bindable)
| #{linkText ? linkText : 'plans and pricing'}
mixin linkPrintNewTab(linkText, linkClass, icon, track)
@ -88,14 +88,14 @@ mixin linkPrintNewTab(linkText, linkClass, icon, track)
if icon
i(class="fa fa-print")
|  
| #{linkText ? linkText : 'print'}
span(ng-non-bindable) #{linkText ? linkText : 'print'}
mixin linkSignIn(linkText, linkClass, redirect)
a(href=`/login${redirect ? '?redir=' + redirect : ''}` class=linkClass ? linkClass : '')
a(href=`/login${redirect ? '?redir=' + redirect : ''}` class=linkClass ? linkClass : '', ng-non-bindable)
| #{linkText ? linkText : 'sign in'}
mixin linkSignUp(linkText, linkClass, redirect)
a(href=`/register${redirect ? '?redir=' + redirect : ''}` class=linkClass ? linkClass : '')
a(href=`/register${redirect ? '?redir=' + redirect : ''}` class=linkClass ? linkClass : '', ng-non-bindable)
| #{linkText ? linkText : 'sign up'}
mixin linkTweet(linkText, linkClass, tweetText, track)
@ -119,5 +119,5 @@ mixin linkTweet(linkText, linkClass, tweetText, track)
) #{linkText ? linkText : 'tweet'}
mixin linkUniversities(linkText, linkClass)
a(href=(settings.siteUrl ? settings.siteUrl : '') + "/for/universities" class=linkClass ? linkClass : '')
a(href=(settings.siteUrl ? settings.siteUrl : '') + "/for/universities" class=linkClass ? linkClass : '', ng-non-bindable)
| #{linkText ? linkText : 'universities'}

View file

@ -11,7 +11,7 @@ block content
tabset(ng-cloak)
tab(heading="System Messages")
each message in systemMessages
.alert.alert-info.row-spaced #{message.content}
.alert.alert-info.row-spaced(ng-non-bindable) #{message.content}
hr
form(method='post', action='/admin/messages')
input(name="_csrf", type="hidden", value=csrfToken)
@ -29,10 +29,10 @@ block content
.row-spaced
ul
each agents, url in openSockets
li #{url} - total : #{agents.length}
li(ng-non-bindable) #{url} - total : #{agents.length}
ul
each agent in agents
li #{agent}
li(ng-non-bindable) #{agent}
tab(heading="Close Editor")
.row-spaced

View file

@ -17,5 +17,5 @@ html.full-height(itemscope, itemtype='http://schema.org/Product')
)
.error-details
p.error-status Something went wrong, sorry.
p.error-description Our staff are probably looking into this, but if it continues, please contact us at #{settings.adminEmail}
p.error-description(ng-non-bindable) Our staff are probably looking into this, but if it continues, please contact us at #{settings.adminEmail}
a.error-btn(href="/") Home

View file

@ -7,7 +7,7 @@ block content
.col-md-8.col-md-offset-2.text-center
.page-header
h1 Maintenance
p
p (ng-non-bindable)
| Sorry, #{settings.appName} is briefly down for maintenance.
| We should be back within minutes, but if not, or you have
| an urgent request, please contact us at

View file

@ -37,7 +37,7 @@ footer.site-footer
ul.col-md-3.text-right
each item in nav.right_footer
li
li(ng-non-bindable)
if item.url
a(href=item.url, class=item.class, aria-label=item.label) !{item.text}
else

View file

@ -6,7 +6,7 @@ nav.navbar.navbar-default.navbar-main
if settings.nav.custom_logo
a(href='/', aria-label=settings.appName, style='background-image:url("'+settings.nav.custom_logo+'")').navbar-brand
else if (nav.title)
a(href='/', aria-label=settings.appName).navbar-title #{nav.title}
a(href='/', aria-label=settings.appName, ng-non-bindable).navbar-title #{nav.title}
else
a(href='/', aria-label=settings.appName).navbar-brand
@ -82,7 +82,7 @@ nav.navbar.navbar-default.navbar-main
b.caret
ul.dropdown-menu
li
div.subdued #{getUserEmail()}
div.subdued(ng-non-bindable) #{getUserEmail()}
li.divider
li
a(href="/user/settings") #{translate('Account Settings')}

View file

@ -50,7 +50,8 @@
p
| #{translate("generic_history_error")}
a(
ng-href="mailto:#{settings.adminEmail}?Subject=Error%20loading%20history%20for%project%20{{ project_id }}"
ng-href="mailto:#{settings.adminEmail}?Subject=Error%20loading%20history%20for%project%20{{ project_id }}",
ng-non-bindable
) #{settings.adminEmail}
p.clearfix
a.alert-link-as-btn.pull-right(

View file

@ -9,12 +9,12 @@ block content
.page-header.text-centered
h1 #{translate("user_wants_you_to_see_project", {username:owner.first_name, projectname:""})}
em
span.project-name #{project.name}
span.project-name(ng-non-bindable) #{project.name}
.row.text-center
.col-md-12
p
| #{translate("accepting_invite_as")} 
em #{user.email}
em(ng-non-bindable) #{user.email}
.row
.col-md-12
form.form(

View file

@ -94,7 +94,7 @@ block content
ng-click="toggle()"
)
i.fa.fa-fw(ng-class="{ 'fa-chevron-up': !visible, 'fa-close': visible }" aria-hidden="true")
span.sr-only Toggle welcome to #{settings.appName} message
span.sr-only(ng-non-bindable) Toggle welcome to #{settings.appName} message
| Welcome to Overleaf v2!
div(ng-show="visible") #[a(href="https://www.overleaf.com/help/342-overleaf-v2-faq") Find out more].
if userIsFromOLv1(user)

View file

@ -33,7 +33,10 @@
li.dropdown-header #{translate("institution")} #{translate("templates")}
for portal in portalTemplates
li
a.menu-indent(href=portal.url + "#templates") #{portal.name}
a.menu-indent(
href=portal.url + "#templates",
ng-non-bindable
) #{portal.name}

View file

@ -27,9 +27,9 @@ block content
else
if hasOwner
p.text-center.row-spaced-small
| #[strong #{name}] has not yet been moved into the new version of
| Overleaf. You will need to move it in order to continue working
| on it. It should only take a few seconds.
| #[strong(ng-non-bindable) #{name}] has not yet been moved into
| the new version of Overleaf. You will need to move it in order
| to continue working on it. It should only take a few seconds.
form(
async-form="v2Import"
@ -50,12 +50,12 @@ block content
a(href="/overleaf/project/" + projectId + "/download/zip") Download project zip file
else
p.text-center.row-spaced.small
| #[strong #{name}] has not yet been moved into the new version of
| Overleaf. This project was created anonymously and therefore
| cannot be automatically imported. Please download a zip file of
| the project and upload that to continue editing it. If you
| would like to delete this project after you have made a copy,
| please contact support.
| #[strong(ng-non-bindable) #{name}] has not yet been moved into
| the new version of Overleaf. This project was created
| anonymously and therefore cannot be automatically imported.
| Please download a zip file of the project and upload that to
| continue editing it. If you would like to delete this project
| after you have made a copy, please contact support.
.row-spaced.text-center
a.btn.btn-primary(href="/overleaf/project/" + projectId + "/download/zip") Download project zip file

View file

@ -22,7 +22,7 @@ block content
each project in projects
tr
- project_id = project._id.toString()
td(width="50%") #{project.name}
td(width="50%", ng-non-bindable) #{project.name}
td(width="25%")
a.btn(href="/project/"+project_id+"/zip") Download latest version as Zip

View file

@ -5,4 +5,4 @@ script(type='text/ng-template', id='scribtexModalTemplate')
p ScribTeX has moved to <strong>https://scribtex.sharelatex.com</strong>. Please update your bookmarks.
p(style="text-align: center") You can find the page you were looking for here:
p(style="text-align: center")
a(href="https://scribtex.sharelatex.com"+scribtexPath, style="font-size: 16px") https://scribtex.sharelatex.com#{scribtexPath}
a(href="https://scribtex.sharelatex.com"+scribtexPath, style="font-size: 16px", ng-non-bindable) https://scribtex.sharelatex.com#{scribtexPath}

View file

@ -28,7 +28,7 @@ mixin table_premium
else
| #{translate(feature.feature)}
for plan in feature.plans
td
td(ng-non-bindable)
if feature.value == 'str'
| #{plan}
else if plan
@ -86,7 +86,7 @@ mixin table_student
span(tooltip=translate(feature.info)) #{translate(feature.feature)}
else
| #{translate(feature.feature)}
td
td(ng-non-bindable)
if feature.value == 'str'
| #{feature.plans.free}
else if feature.plans.free
@ -95,9 +95,9 @@ mixin table_student
else
i.fa.fa-times(aria-hidden="true")
span.sr-only Feature included
td
td(ng-non-bindable)
+table_cell_student(feature)
td
td(ng-non-bindable)
+table_cell_student(feature)
tr

View file

@ -41,10 +41,10 @@ block content
-if (!hasDisplayedSubscription)
-if (hasSubscription)
-hasDisplayedSubscription = true
p You're on an #{settings.appName} Paid plan. Contact
p(ng-non-bindable) You're on an #{settings.appName} Paid plan. Contact
a(href="mailto:support@overleaf.com") support@overleaf.com
| to find out more.
-else
p You're on the #{settings.appName} Free plan.
p(ng-non-bindable) You're on the #{settings.appName} Free plan.
|
a(href="/user/subscription/plans").btn.btn-primary Upgrade now

View file

@ -2,7 +2,7 @@ mixin printPlan(plan)
-if (!plan.hideFromUsers)
tr(ng-controller="ChangePlanFormController", ng-init="plan="+JSON.stringify(plan))
td
strong #{plan.name}
strong(ng-non-bindable) #{plan.name}
td
-if (plan.annual)
| {{price}} / #{translate("year")}

View file

@ -9,7 +9,7 @@ div(ng-controller="GroupMembershipController")
- if (groupSubscription.teamNotice && groupSubscription.teamNotice != '')
p
//- Team notice is sanitized in SubscriptionViewModelBuilder
em !{groupSubscription.teamNotice}
em(ng-non-bindable) !{groupSubscription.teamNotice}
span
button.btn.btn-danger.text-capitalise(ng-click="removeSelfFromGroup('"+groupSubscription.admin_id._id+"')") #{translate("leave_group")}
hr

View file

@ -4,7 +4,7 @@ each institution in confirmedMemberInstitutions
p
| You have a
|
strong Professional
strong(ng-non-bindable) Professional
|
| #{settings.appName} account as a confirmed member of
|

View file

@ -11,7 +11,7 @@ div(ng-controller="RecurlySubscriptionController")
p !{translate("currently_subscribed_to_plan", {planName:"<strong>" + personalSubscription.plan.name + "</strong>"})}
a(href, ng-click="switchToChangePlanView()", ng-if="showChangePlanButton") !{translate("change_plan")}.
-if (personalSubscription.recurly.trialEndsAtFormatted && personalSubscription.recurly.trial_ends_at > Date.now())
p You're on a free trial which ends on <strong>#{personalSubscription.recurly.trialEndsAtFormatted}</strong>
p You're on a free trial which ends on <strong ng-non-bindable>#{personalSubscription.recurly.trialEndsAtFormatted}</strong>
p !{translate("next_payment_of_x_collectected_on_y", {paymentAmmount:"<strong>" + personalSubscription.recurly.price + "</strong>", collectionDate:"<strong>" + personalSubscription.recurly.nextPaymentDueAt + "</strong>"})}
p.pull-right
p

View file

@ -244,7 +244,7 @@ block content
hr
p.small.text-center We're confident that you'll love #{settings.appName}, but if not you can cancel anytime. We'll give you your money back, no questions asked, if you let us know within 30 days.
p.small.text-center(ng-non-bindable) We're confident that you'll love #{settings.appName}, but if not you can cancel anytime. We'll give you your money back, no questions asked, if you let us know within 30 days.
script(type="text/javascript").

View file

@ -19,7 +19,7 @@ block content
.row
.col-md-12
.page-header.centered.plans-header.text-centered
h1.text-capitalize #{translate('get_instant_access_to')} #{settings.appName}
h1.text-capitalize(ng-non-bindable) #{translate('get_instant_access_to')} #{settings.appName}
.row
.col-md-8.col-md-offset-2
p.text-centered #{translate("sl_benefits_plans")}

View file

@ -18,10 +18,10 @@ block content
p.letter-from-founders
p #{translate("thanks_for_subscribing_you_help_sl", {planName:subscription.plan.name})}
p #{translate("need_anything_contact_us_at")}
a(href=`mailto:${settings.adminEmail}`) #{settings.adminEmail}
a(href=`mailto:${settings.adminEmail}`, ng-non-bindable) #{settings.adminEmail}
| .
p #{translate("regards")},
br
br(ng-non-bindable)
| The #{settings.appName} Team
p
a.btn.btn-primary(href="/project") &lt; #{translate("back_to_your_projects")}

View file

@ -5,7 +5,7 @@ block content
.container
.row
.col-md-12
h1 !{viewData.title}
h1(ng-non-bindable) !{viewData.title}
.row.row-spaced
.pattern-container
@ -14,6 +14,6 @@ block content
.row
.col-md-10.col-md-offset-1
.card
.row
.row(ng-non-bindable)
| !{viewData.html}

View file

@ -7,7 +7,7 @@ block content
.registration_message
if sharedProjectData.user_first_name !== undefined
h1 #{translate("user_wants_you_to_see_project", {username:sharedProjectData.user_first_name, projectname:""})}
em #{sharedProjectData.project_name}
em(ng-non-bindable) #{sharedProjectData.project_name}
div
| #{translate("join_sl_to_view_project")}.
div
@ -26,5 +26,5 @@ block content
h1 #{translate("register")}
p
| Please contact
strong #{settings.adminEmail}
strong(ng-non-bindable) #{settings.adminEmail}
| to create an account.

View file

@ -41,7 +41,10 @@ block content
// show the email, non-editable
.form-group
label.control-label #{translate("email")}
div.form-control(readonly="true") #{user.email}
div.form-control(
readonly="true",
ng-non-bindable
) #{user.email}
if shouldAllowEditingDetails
.form-group
@ -68,10 +71,16 @@ block content
else
.form-group
label.control-label #{translate("first_name")}
div.form-control(readonly="true") #{user.first_name}
div.form-control(
readonly="true",
ng-non-bindable
) #{user.first_name}
.form-group
label.control-label #{translate("last_name")}
div.form-control(readonly="true") #{user.last_name}
div.form-control(
readonly="true",
ng-non-bindable
) #{user.last_name}
.col-md-5.col-md-offset-1
h3 #{translate("change_password")}

View file

@ -5,7 +5,7 @@ block content
.container
.row
.col-md-10.col-md-offset-1
h1 #{name || translate(translations.title)}
h1(ng-non-bindable) #{name || translate(translations.title)}
.card(ng-controller="UserMembershipController")
.page-header
.pull-right(ng-cloak)

View file

@ -5,11 +5,14 @@ block content
.container
.row
.col-md-10.col-md-offset-1
h3 #{entityName} "#{entityId}" does not exists in v2
h3(ng-non-bindable) #{entityName} "#{entityId}" does not exists in v2
form(
enctype='application/json',
method='post',
action=''
)
input(name="_csrf", type="hidden", value=csrfToken)
button.btn.btn-primary.text-capitalize(type="submit") Create #{entityName} in v2
button.btn.btn-primary.text-capitalize(
type="submit",
ng-non-bindable
) Create #{entityName} in v2

View file

@ -1,70 +1,37 @@
/* eslint-disable
max-len,
no-undef,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* DS103: Rewrite code to no longer use __guard__
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
define(['base'], App =>
App.directive('mathjax', () => ({
/* global MathJax, _ */
define(['base'], function(App) {
return App.directive('mathjax', function($compile) {
return {
link(scope, element, attrs) {
if (!(MathJax && MathJax.Hub)) return
const mathJaxContents = element.html()
const nonBindableEl = $compile('<span ng-non-bindable></span>')({})
element.html('').append(nonBindableEl)
nonBindableEl.html(mathJaxContents)
if (attrs.delimiter !== 'no-single-dollar') {
const inlineMathConfig = __guard__(
__guard__(
typeof MathJax !== 'undefined' && MathJax !== null
? MathJax.Hub
: undefined,
x1 => x1.config
),
x => x.tex2jax.inlineMath
)
const inlineMathConfig =
MathJax.Hub.config && MathJax.Hub.config.tex2jax.inlineMath
const alreadyConfigured = _.find(
inlineMathConfig,
c => c[0] === '$' && c[1] === '$'
)
if (alreadyConfigured == null) {
__guard__(
typeof MathJax !== 'undefined' && MathJax !== null
? MathJax.Hub
: undefined,
x2 =>
x2.Config({
if (!alreadyConfigured) {
MathJax.Hub.Config({
tex2jax: {
inlineMath: inlineMathConfig.concat([['$', '$']])
}
})
)
}
}
return setTimeout(
() =>
__guard__(
typeof MathJax !== 'undefined' && MathJax !== null
? MathJax.Hub
: undefined,
x3 =>
x3.Queue([
'Typeset',
typeof MathJax !== 'undefined' && MathJax !== null
? MathJax.Hub
: undefined,
element.get(0)
])
),
0
)
setTimeout(() => {
MathJax.Hub.Queue(['Typeset', MathJax.Hub, element.get(0)])
}, 0)
}
})))
function __guard__(value, transform) {
return typeof value !== 'undefined' && value !== null
? transform(value)
: undefined
}
})
})