0
0
mirror of https://github.com/go-gitea/gitea.git synced 2025-11-06 16:40:31 +01:00
gitea/modules/markup/sanitizer_default.go
Giteabot e194d89c74
Improve and fix markup code preview rendering (#35777) (#35787)
Backport #35777 by @silverwind

1. Add the color on the link to the referenced file, which is the more
likely thing the user wants to click
2. Use monospace font on the SHA
3. Tweak text colors
4. Change SHA link to go to the commit instead of the repo root with
commit filter set
5. Added the repo name to the file link text
6. Fix broken line numbering rendering

The only major difference to GitHub is now the missing line numbers.

Before:

<img width="286" height="162" alt="Screenshot 2025-10-29 at 19 09 59"
src="https://github.com/user-attachments/assets/f16b4eec-caf2-4c31-a2b5-ae5f41747d4b"
/>

After:

<img width="378" height="157" alt="image"
src="https://github.com/user-attachments/assets/0c91dfd3-0910-4b2d-a43b-8c87cfbb933e"
/>

For comparison, GitHub rendering:

<img width="286" height="177" alt="image"
src="https://github.com/user-attachments/assets/8a9a07b7-9153-4415-9d7a-5685853e472a"
/>

Co-authored-by: silverwind <me@silverwind.io>
2025-10-30 09:06:44 +00:00

112 lines
4.2 KiB
Go

// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package markup
import (
"html/template"
"io"
"net/url"
"regexp"
"code.gitea.io/gitea/modules/setting"
"github.com/microcosm-cc/bluemonday"
)
func (st *Sanitizer) createDefaultPolicy() *bluemonday.Policy {
policy := bluemonday.UGCPolicy()
// NOTICE: DO NOT add special "class" regexp rules here anymore, use RenderInternal.SafeAttr instead
// General safe SVG attributes
policy.AllowAttrs("viewBox", "width", "height", "aria-hidden", "data-attr-class").OnElements("svg")
policy.AllowAttrs("fill-rule", "d").OnElements("path")
// Checkboxes
policy.AllowAttrs("type").Matching(regexp.MustCompile(`^checkbox$`)).OnElements("input")
policy.AllowAttrs("checked", "disabled", "data-source-position").OnElements("input")
// Chroma always uses 1-2 letters for style names, we could tolerate it at the moment
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^\w{0,2}$`)).OnElements("span")
// Line numbers on codepreview
policy.AllowAttrs("data-line-number").OnElements("span")
// Custom URL-Schemes
if len(setting.Markdown.CustomURLSchemes) > 0 {
policy.AllowURLSchemes(setting.Markdown.CustomURLSchemes...)
} else {
policy.AllowURLSchemesMatching(st.allowAllRegex)
// Even if every scheme is allowed, these three are blocked for security reasons
disallowScheme := func(*url.URL) bool {
return false
}
policy.AllowURLSchemeWithCustomPolicy("javascript", disallowScheme)
policy.AllowURLSchemeWithCustomPolicy("vbscript", disallowScheme)
policy.AllowURLSchemeWithCustomPolicy("data", disallowScheme)
}
// Allow classes for org mode list item status.
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^(unchecked|checked|indeterminate)$`)).OnElements("li")
// Allow 'color' and 'background-color' properties for the style attribute on text elements.
policy.AllowStyles("color", "background-color").OnElements("div", "span", "p", "tr", "th", "td")
policy.AllowAttrs("src", "autoplay", "controls").OnElements("video")
policy.AllowAttrs("loading").OnElements("img")
// Allow generally safe attributes (reference: https://github.com/jch/html-pipeline)
generalSafeAttrs := []string{
"abbr", "accept", "accept-charset",
"accesskey", "action", "align", "alt",
"aria-describedby", "aria-hidden", "aria-label", "aria-labelledby",
"axis", "border", "cellpadding", "cellspacing", "char",
"charoff", "charset", "checked",
"clear", "cols", "colspan", "color",
"compact", "coords", "datetime", "dir",
"disabled", "enctype", "for", "frame",
"headers", "height", "hreflang",
"hspace", "ismap", "label", "lang",
"maxlength", "media", "method",
"multiple", "name", "nohref", "noshade",
"nowrap", "open", "prompt", "readonly", "rel", "rev",
"rows", "rowspan", "rules", "scope",
"selected", "shape", "size", "span",
"start", "summary", "tabindex", "target",
"title", "type", "usemap", "valign", "value",
"vspace", "width", "itemprop", "itemscope", "itemtype",
"data-markdown-generated-content", "data-attr-class",
}
generalSafeElements := []string{
"h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8", "br", "b", "i", "strong", "em", "a", "pre", "code", "img", "tt",
"div", "ins", "del", "sup", "sub", "p", "ol", "ul", "table", "thead", "tbody", "tfoot", "blockquote", "label",
"dl", "dt", "dd", "kbd", "q", "samp", "var", "hr", "ruby", "rt", "rp", "li", "tr", "td", "th", "s", "strike", "summary",
"details", "caption", "figure", "figcaption",
"abbr", "bdo", "cite", "dfn", "mark", "small", "span", "time", "video", "wbr",
}
// FIXME: Need to handle longdesc in img but there is no easy way to do it
policy.AllowAttrs(generalSafeAttrs...).OnElements(generalSafeElements...)
// Custom keyword markup
defaultSanitizer.addSanitizerRules(policy, setting.ExternalSanitizerRules)
return policy
}
// Sanitize use default sanitizer policy to sanitize a string
func Sanitize(s string) template.HTML {
return template.HTML(GetDefaultSanitizer().defaultPolicy.Sanitize(s))
}
// SanitizeReader sanitizes a Reader
func SanitizeReader(r io.Reader, renderer string, w io.Writer) error {
policy, exist := GetDefaultSanitizer().rendererPolicies[renderer]
if !exist {
policy = GetDefaultSanitizer().defaultPolicy
}
return policy.SanitizeReaderToWriter(r, w)
}