diff --git a/api/http/handler/customtemplates/customtemplate_create.go b/api/http/handler/customtemplates/customtemplate_create.go index 60727396b..f79aac9e9 100644 --- a/api/http/handler/customtemplates/customtemplate_create.go +++ b/api/http/handler/customtemplates/customtemplate_create.go @@ -3,6 +3,7 @@ package customtemplates import ( "errors" "net/http" + "regexp" "strconv" "github.com/asaskevich/govalidator" @@ -129,9 +130,20 @@ func (payload *customTemplateFromFileContentPayload) Validate(r *http.Request) e if payload.Type != portainer.KubernetesStack && payload.Type != portainer.DockerSwarmStack && payload.Type != portainer.DockerComposeStack { return errors.New("Invalid custom template type") } + if !isValidNote(payload.Note) { + return errors.New("Invalid note. tag is not supported") + } return nil } +func isValidNote(note string) bool { + if govalidator.IsNull(note) { + return true + } + match, _ := regexp.MatchString(" tag is not supported") + } return nil } @@ -285,6 +300,9 @@ func (payload *customTemplateFromFileUploadPayload) Validate(r *http.Request) er payload.Logo = logo note, _ := request.RetrieveMultiPartFormValue(r, "Note", true) + if !isValidNote(note) { + return errors.New("Invalid note. tag is not supported") + } payload.Note = note typeNumeral, _ := request.RetrieveNumericMultiPartFormValue(r, "Type", true) diff --git a/api/http/handler/customtemplates/customtemplate_update.go b/api/http/handler/customtemplates/customtemplate_update.go index dcbb1dd65..0deac2c17 100644 --- a/api/http/handler/customtemplates/customtemplate_update.go +++ b/api/http/handler/customtemplates/customtemplate_update.go @@ -51,6 +51,9 @@ func (payload *customTemplateUpdatePayload) Validate(r *http.Request) error { if govalidator.IsNull(payload.Description) { return errors.New("Invalid custom template description") } + if !isValidNote(payload.Note) { + return errors.New("Invalid note. tag is not supported") + } return nil } diff --git a/app/portainer/models/tag.js b/app/portainer/models/tag.js index 38bea58fb..ee3660ca9 100644 --- a/app/portainer/models/tag.js +++ b/app/portainer/models/tag.js @@ -1,4 +1,6 @@ +import _ from 'lodash-es'; + export function TagViewModel(data) { this.Id = data.ID; - this.Name = data.Name; + this.Name = _.escape(data.Name); } diff --git a/app/portainer/models/team.js b/app/portainer/models/team.js index c8d583133..617b36ce9 100644 --- a/app/portainer/models/team.js +++ b/app/portainer/models/team.js @@ -1,5 +1,7 @@ +import _ from 'lodash-es'; + export function TeamViewModel(data) { this.Id = data.Id; - this.Name = data.Name; + this.Name = _.escape(data.Name); this.Checked = false; } diff --git a/app/portainer/services/api/customTemplate.js b/app/portainer/services/api/customTemplate.js index 12d7d4688..641f4bcd4 100644 --- a/app/portainer/services/api/customTemplate.js +++ b/app/portainer/services/api/customTemplate.js @@ -3,15 +3,21 @@ import angular from 'angular'; angular.module('portainer.app').factory('CustomTemplateService', CustomTemplateServiceFactory); /* @ngInject */ -function CustomTemplateServiceFactory(CustomTemplates, FileUploadService) { +function CustomTemplateServiceFactory($sanitize, CustomTemplates, FileUploadService) { var service = {}; service.customTemplate = function customTemplate(id) { return CustomTemplates.get({ id }).$promise; }; - service.customTemplates = function customTemplates(type) { - return CustomTemplates.query({ type }).$promise; + service.customTemplates = async function customTemplates(type) { + const templates = await CustomTemplates.query({ type }).$promise; + templates.forEach((template) => { + if (template.Note) { + template.Note = $('

').html($sanitize(template.Note)).find('img').remove().end().html(); + } + }); + return templates; }; service.remove = function remove(id) { diff --git a/app/portainer/services/notifications.js b/app/portainer/services/notifications.js index db401e4bd..51f98ff5e 100644 --- a/app/portainer/services/notifications.js +++ b/app/portainer/services/notifications.js @@ -1,3 +1,4 @@ +import _ from 'lodash-es'; import toastr from 'toastr'; angular.module('portainer.app').factory('Notifications', [ @@ -7,11 +8,11 @@ angular.module('portainer.app').factory('Notifications', [ var service = {}; service.success = function (title, text) { - toastr.success($sanitize(text), $sanitize(title)); + toastr.success($sanitize(_.escape(text)), $sanitize(title)); }; service.warning = function (title, text) { - toastr.warning($sanitize(text), $sanitize(title), { timeOut: 6000 }); + toastr.warning($sanitize(_.escape(text)), $sanitize(title), { timeOut: 6000 }); }; service.error = function (title, e, fallbackText) { @@ -44,7 +45,7 @@ angular.module('portainer.app').factory('Notifications', [ console.error(e); if (msg !== 'Invalid JWT token') { - toastr.error($sanitize(msg), $sanitize(title), { timeOut: 6000 }); + toastr.error($sanitize(_.escape(msg)), $sanitize(title), { timeOut: 6000 }); } };