You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@answer.apache.org by li...@apache.org on 2026/09/22 08:04:12 UTC
(answer) 02/16: fix: normalize imported content
This is an automated email from the ASF dual-hosted git repository.
LinkinStars pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/answer.git
commit 1a8627e26e9b70713b140fedae7f8606a50d2203
Author: LinkinStars <li...@foxmail.com>
AuthorDate: Fri Aug 14 16:48:53 2026 +0800
fix: normalize imported content
---
internal/service/importer/importer_service.go | 29 +++++++++------
internal/service/importer/importer_service_test.go | 41 ++++++++++++++++++++++
2 files changed, 59 insertions(+), 11 deletions(-)
diff --git a/internal/service/importer/importer_service.go b/internal/service/importer/importer_service.go
index 9d12bf07..1842479b 100644
--- a/internal/service/importer/importer_service.go
+++ b/internal/service/importer/importer_service.go
@@ -32,6 +32,7 @@ import (
"github.com/apache/answer/internal/service/permission"
"github.com/apache/answer/internal/service/rank"
usercommon "github.com/apache/answer/internal/service/user_common"
+ "github.com/apache/answer/pkg/converter"
"github.com/apache/answer/plugin"
"github.com/gin-gonic/gin"
"github.com/segmentfault/pacman/errors"
@@ -70,7 +71,7 @@ func (ip *ImporterService) NewImporterFunc() plugin.ImporterFunc {
}
func (ip *ImporterService) ImportQuestion(ctx context.Context, questionInfo plugin.QuestionImporterInfo) (err error) {
- req := &schema.QuestionAdd{}
+ req := newImportedQuestionRequest(questionInfo)
errFields := make([]*validator.FormErrorField, 0)
// To limit rate, remove the following code from comment: Part 1/2
// reject, rejectKey := ipc.rateLimitMiddleware.DuplicateRequestRejection(ctx, req)
@@ -94,16 +95,6 @@ func (ip *ImporterService) ImportQuestion(ctx context.Context, questionInfo plug
// }
// }()
req.UserID = userInfo.ID
- req.Title = questionInfo.Title
- req.Content = questionInfo.Content
- req.HTML = "<p>" + questionInfo.Content + "</p>"
- req.Tags = make([]*schema.TagItem, len(questionInfo.Tags))
- for i, tag := range questionInfo.Tags {
- req.Tags[i] = &schema.TagItem{
- SlugName: tag,
- DisplayName: tag,
- }
- }
canList, requireRanks, err := ip.rankService.CheckOperationPermissionsForRanks(ctx, req.UserID, []string{
permission.QuestionAdd,
permission.QuestionEdit,
@@ -169,3 +160,19 @@ func (ip *ImporterService) ImportQuestion(ctx context.Context, questionInfo plug
log.Info("Add Question Successfully")
return nil
}
+
+func newImportedQuestionRequest(questionInfo plugin.QuestionImporterInfo) *schema.QuestionAdd {
+ req := &schema.QuestionAdd{
+ Title: questionInfo.Title,
+ Content: questionInfo.Content,
+ HTML: converter.Markdown2HTML(questionInfo.Content),
+ Tags: make([]*schema.TagItem, len(questionInfo.Tags)),
+ }
+ for i, tag := range questionInfo.Tags {
+ req.Tags[i] = &schema.TagItem{
+ SlugName: tag,
+ DisplayName: tag,
+ }
+ }
+ return req
+}
diff --git a/internal/service/importer/importer_service_test.go b/internal/service/importer/importer_service_test.go
new file mode 100644
index 00000000..ff32740b
--- /dev/null
+++ b/internal/service/importer/importer_service_test.go
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package importer
+
+import (
+ "strings"
+ "testing"
+
+ "github.com/apache/answer/plugin"
+)
+
+func TestNewImportedQuestionRequestSanitizesContent(t *testing.T) {
+ request := newImportedQuestionRequest(plugin.QuestionImporterInfo{
+ Title: "Imported question",
+ Content: `<img src=x onerror=alert(1)><script>alert(1)</script>`,
+ Tags: []string{"security"},
+ })
+
+ for _, unsafeContent := range []string{"onerror", "<script"} {
+ if strings.Contains(strings.ToLower(request.HTML), unsafeContent) {
+ t.Fatalf("imported question HTML contains unsafe content %q: %s", unsafeContent, request.HTML)
+ }
+ }
+}