fix(ui): hardcode sort options in search syntax hint, improve look #11381

Merged
0ko merged 6 commits from 0ko/ui-search-syntax-but-without-allowing-scripts into forgejo 2026-02-23 06:03:25 +01:00 AGit
Owner

Followup to #9109

Fix issue reported by @mahlzahn that the string was confusing translators and they translated the part that wasn't meant to be translated
https://translate.codeberg.org/translate/forgejo/forgejo-next/en/?checksum=54d85b848166f618#translations
(this link is now broken because the string was replaced and weblate forgot it)

Part of this fix was to replace custom IterWithTr with simple dict iteration to allow for placeholders in strings.

Fix issue where <script>alert('🐸')</script> in locales would have been rendered. Similar to #7740. Locales are considered UGC as there are too many for developers to make sure they're not causing bugs, but in this case they are guarded by linter lint-locale.go. #11381 (comment)

Release notes

  • User Interface bug fixes
    • PR: fix(ui): hardcode sort options in search syntax hint, improve look
Followup to https://codeberg.org/forgejo/forgejo/pulls/9109 Fix issue reported by @mahlzahn that the string was confusing translators and they translated the part that wasn't meant to be translated https://translate.codeberg.org/translate/forgejo/forgejo-next/en/?checksum=54d85b848166f618#translations (this link is now broken because the string was replaced and weblate forgot it) Part of this fix was to replace custom IterWithTr with simple dict iteration to allow for placeholders in strings. ~~Fix issue where `<script>alert('🐸')</script>` in locales would have been rendered. Similar to https://codeberg.org/forgejo/forgejo/pulls/7740. Locales are considered UGC as there are too many for developers to make sure they're not causing bugs, but in this case they are guarded by linter `lint-locale.go`.~~ https://codeberg.org/forgejo/forgejo/pulls/11381#issuecomment-10866701 <!--start release-notes-assistant--> ## Release notes <!--URL:https://codeberg.org/forgejo/forgejo--> - User Interface bug fixes - [PR](https://codeberg.org/forgejo/forgejo/pulls/11381): <!--number 11381 --><!--line 0 --><!--description Zml4KHVpKTogaGFyZGNvZGUgc29ydCBvcHRpb25zIGluIHNlYXJjaCBzeW50YXggaGludCwgaW1wcm92ZSBsb29r-->fix(ui): hardcode sort options in search syntax hint, improve look<!--description--> <!--end release-notes-assistant-->
it is for rendering raw trusted text as actual html, which translations are not

in both cases, adding `<script>alert('0ko')</script>` to the locale string causes script to execute, so SafeHTML does nothing here

it may need to be removed because it already caught at least two people thinking that it's safe to use it
to fix the issue where many translators got confused and thought that these were translatable

the key was changed to avoid either mass-updating the string in all locales or mass-breaking them
as i am here, replacing the button with newer equivalent
Some checks failed
testing / semgrep/ci (pull_request) Successful in 16s
testing / frontend-checks (pull_request) Successful in 1m4s
testing / backend-checks (pull_request) Successful in 2m49s
issue-labels / backporting (pull_request_target) Has been skipped
issue-labels / cascade (pull_request_target) Has been skipped
requirements / merge-conditions (pull_request) Successful in 3s
issue-labels / release-notes (pull_request_target) Has been cancelled
testing / test-mysql (pull_request) Has been cancelled
testing / test-unit (pull_request) Has been cancelled
testing / test-pgsql (pull_request) Has been cancelled
testing / test-e2e (pull_request) Has been cancelled
testing / test-sqlite (pull_request) Has been cancelled
testing / test-remote-cacher (redis) (pull_request) Has been cancelled
testing / test-remote-cacher (valkey) (pull_request) Has been cancelled
testing / test-remote-cacher (garnet) (pull_request) Has been cancelled
testing / test-remote-cacher (redict) (pull_request) Has been cancelled
testing / security-check (pull_request) Has been cancelled
85839973c5
also class icon was not needed as there was no icon in the button
oops i submitted it broken
All checks were successful
testing / semgrep/ci (pull_request) Successful in 14s
testing / frontend-checks (pull_request) Successful in 1m19s
testing / backend-checks (pull_request) Successful in 3m26s
requirements / merge-conditions (pull_request) Successful in 4s
issue-labels / release-notes (pull_request_target) Successful in 29s
testing / test-unit (pull_request) Successful in 7m6s
testing / test-remote-cacher (redict) (pull_request) Successful in 2m12s
testing / test-remote-cacher (valkey) (pull_request) Successful in 2m14s
testing / test-remote-cacher (redis) (pull_request) Successful in 2m15s
testing / test-remote-cacher (garnet) (pull_request) Successful in 2m14s
testing / test-e2e (pull_request) Successful in 20m21s
testing / test-mysql (pull_request) Successful in 22m46s
testing / test-sqlite (pull_request) Successful in 27m48s
testing / test-pgsql (pull_request) Successful in 30m51s
testing / security-check (pull_request) Successful in 53s
9183ffb1da
0ko requested review from snematoda 2026-02-20 19:30:47 +01:00
@ -19,0 +14,4 @@
"assignee:<username>" (ctx.Locale.TrString "repo.issues.filter_assignee.hint")
"review:<username>" (ctx.Locale.TrString "repo.issues.filter_reviewers.hint")
"mentions:<username>" (ctx.Locale.TrString "repo.issues.filter_mention.hint")
"sort:<by>:[asc|desc]" (ctx.Locale.TrString "repo.issues.filter_sort.hint_with_placeholder" "created/comments/updated/deadline")
Member

Maybe put the options in <code> element? And for consistency with pipes instead of slashes?

Maybe put the options in `<code>` element? And for consistency with pipes instead of slashes?
Author
Owner

Regarding <code>, it is close to impossible to implement it in the current way while retaining the script escaping. For that we would need some new version of TrString that HTMLEscapes the string itself and HTMLFormats placeholder values.

I now understand why we resorted to simply guarding the strings we have in the codebase by linting. It's much simpler and only needs to be time prior to runtime.

The issue with inserting scripts is real, but me trying to guard one string is useless, because every string rendered by Tr is affected in the same way.

So I'll drop that part of this PR.

Regarding `<code>`, it is close to impossible to implement it in the current way while retaining the script escaping. For that we would need some new version of `TrString` that HTMLEscapes the string itself and HTMLFormats placeholder values. I now understand why we resorted to simply guarding the strings we have in the codebase by linting. It's much simpler and only needs to be time prior to runtime. The issue with inserting scripts is real, but me trying to guard one string is useless, because every string rendered by `Tr` is affected in the same way. So I'll drop that part of this PR.
Member

OK

OK
Author
Owner

I'll wait for someone to re-approve before merging.

~~I'll wait for someone to re-approve before merging.~~
Member

Can we create a new issue for the string escaping thing?

Can we create a new issue for the string escaping thing?
Member

@0ko wrote in #11381/files (comment):

Regarding <code>, it is close to impossible to implement it in the current way while retaining the script escaping. For that we would need some new version of TrString that HTMLEscapes the string itself and HTMLFormats placeholder values.

Considering that sort is just one out of nine... wouldn't it be simpler to just add that outside the loop :)

@0ko wrote in https://codeberg.org/forgejo/forgejo/pulls/11381/files#issuecomment-10866701: > Regarding `<code>`, it is close to impossible to implement it in the current way while retaining the script escaping. For that we would need some new version of `TrString` that HTMLEscapes the string itself and HTMLFormats placeholder values. Considering that sort is just one out of nine... wouldn't it be simpler to just add that outside the loop :)
Member

One way to do it might be to handle the last case completely outside of the loop (this would also massively cut down on the size of this change).

One can't really handle it "to perfect satisfaction" in the place easily either, e.g. one can't use string parsing on the already substituted translation string because it would assume too much of the sentence structure of arbitrary languages, afaik (e.g. when just appending to the translated string, which would "get around" that problem in a meh way).

One way to do it might be to handle the last case completely outside of the loop (this would also massively cut down on the size of this change). One can't really handle it "to perfect satisfaction" in the place easily either, e.g. one can't use string parsing on the already substituted translation string because it would assume too much of the sentence structure of arbitrary languages, afaik (e.g. when just appending to the translated string, which would "get around" that problem in a meh way).
Author
Owner

I don't see this as a significant issue worty solving because

  1. we have 4500 usages of Locale.Tr in templates, we want them to retain ability for basic html formatting (a, bold, italic) while not allowing undesired formatting (img, script, style), and we already have protection in place for that via lint-locale.
  2. while a lot of surface area can be mitigated by using Locale.TrString, currently it's almost never used in templates, and we won't be able to convert all usages of Locale.Tr to Locale.TrString because (1), so it's not even worth trying
  3. if we have to use Locale.Tr, we can't just have some html tags escaped and some preserved, it will have to be a policy similar to what we have applied to markdown in UGC. But bisecting between good and bad formatting in runtime can't be implemented without degrading performance, and it's not needed because of (1)

The mitigations don't have to be implemented as either new Locale funcs or amended Locale funcs, the way of implementation simply doesn't matter, because it can't be done in a nice way because of (3).

I don't see this as a significant issue worty solving because 1. we have 4500 usages of `Locale.Tr` in templates, we want them to retain ability for basic html formatting (a, bold, italic) while not allowing undesired formatting (img, script, style), and we already have protection in place for that via lint-locale. 2. while a lot of surface area can be mitigated by using `Locale.TrString`, currently it's almost never used in templates, and we won't be able to convert all usages of `Locale.Tr` to `Locale.TrString` because (1), so it's not even worth trying 3. if we have to use `Locale.Tr`, we can't just have some html tags escaped and some preserved, it will have to be a policy similar to what we have applied to markdown in UGC. But bisecting between good and bad formatting in runtime can't be implemented without degrading performance, and it's not needed because of (1) The mitigations don't have to be implemented as either new Locale funcs or amended Locale funcs, the way of implementation simply doesn't matter, because it can't be done in a nice way because of (3).
snematoda approved these changes 2026-02-21 13:33:13 +01:00
snematoda left a comment
Member

🫣 my bad... thank you for cleaning this up! ...and mahlzahn for reporting this!

🫣 my bad... thank you for cleaning this up! ...and mahlzahn for reporting this!
fogti approved these changes 2026-02-21 13:57:45 +01:00
use pipes, add <code>
All checks were successful
testing / semgrep/ci (pull_request) Successful in 12s
testing / frontend-checks (pull_request) Successful in 59s
testing / backend-checks (pull_request) Successful in 3m12s
Integration tests for the release process / release-simulation (pull_request) Successful in 5m38s
testing / test-unit (pull_request) Successful in 6m0s
testing / test-remote-cacher (redict) (pull_request) Successful in 2m9s
testing / test-remote-cacher (garnet) (pull_request) Successful in 2m9s
testing / test-remote-cacher (redis) (pull_request) Successful in 2m10s
testing / test-remote-cacher (valkey) (pull_request) Successful in 2m10s
testing / test-e2e (pull_request) Successful in 18m23s
testing / test-mysql (pull_request) Successful in 20m15s
testing / test-sqlite (pull_request) Successful in 26m19s
testing / test-pgsql (pull_request) Successful in 29m33s
testing / security-check (pull_request) Successful in 58s
milestone / set (pull_request_target) Successful in 5s
requirements / merge-conditions (pull_request) Successful in 2s
issue-labels / backporting (pull_request_target) Successful in 33s
issue-labels / release-notes (pull_request_target) Successful in 23s
62fb5d6275
0ko changed title from fix(ui): hardcode sort options in search syntax hint, fix html to fix(ui): hardcode sort options in search syntax hint, improve look 2026-02-22 11:23:44 +01:00
0ko merged commit f9a22b335e into forgejo 2026-02-23 06:03:25 +01:00
Sign in to join this conversation.
No reviewers
No labels
arch
riscv64
backport/v1.19
backport/v1.20
backport/v1.21/forgejo
backport/v10.0/forgejo
backport/v11.0/forgejo
backport/v12.0/forgejo
backport/v13.0/forgejo
backport/v14.0/forgejo
backport/v7.0/forgejo
backport/v8.0/forgejo
backport/v9.0/forgejo
breaking
bug
bug
confirmed
bug
duplicate
bug
needs-more-info
bug
new-report
bug
reported-upstream
code/actions
code/api
code/auth
code/auth/faidp
code/auth/farp
code/email
code/federation
code/git
code/migrations
code/packages
code/wiki
database
MySQL
database
PostgreSQL
database
SQLite
dependency-upgrade
dependency
certmagic
dependency
chart.js
dependency
Chi
dependency
Chroma
dependency
citation.js
dependency
codespell
dependency
css-loader
dependency
devcontainers
dependency
dropzone
dependency
editorconfig-checker
dependency
elasticsearch
dependency
enmime
dependency
F3
dependency
ForgeFed
dependency
garage
dependency
Git
dependency
git-backporting
dependency
Gitea
dependency
gitignore
dependency
go-ap
dependency
go-enry
dependency
go-gitlab
dependency
Go-org
dependency
go-rpmutils
dependency
go-sql-driver mysql
dependency
go-swagger
dependency
go-version
dependency
go-webauthn
dependency
gocron
dependency
Golang
dependency
goldmark
dependency
goquery
dependency
Goth
dependency
grpc-go
dependency
happy-dom
dependency
Helm
dependency
image-spec
dependency
jsonschema
dependency
KaTeX
dependency
lint
dependency
MariaDB
dependency
Mermaid
dependency
minio-go
dependency
misspell
dependency
Monaco
dependency
PDFobject
dependency
playwright
dependency
postcss
dependency
postcss-plugins
dependency
pprof
dependency
prometheus client_golang
dependency
protobuf
dependency
relative-time-element
dependency
renovate
dependency
reply
dependency
ssh
dependency
swagger-ui
dependency
tailwind
dependency
temporal-polyfill
dependency
terminal-to-html
dependency
tests-only
dependency
text-expander-element
dependency
urfave
dependency
vfsgen
dependency
vite
dependency
Woodpecker CI
dependency
x tools
dependency
XORM
Discussion
duplicate
enhancement/feature
forgejo/accessibility
forgejo/branding
forgejo/ci
forgejo/commit-graph
forgejo/documentation
forgejo/furnace cleanup
forgejo/i18n
forgejo/interop
forgejo/moderation
forgejo/privacy
forgejo/release
forgejo/scaling
forgejo/security
forgejo/ui
Gain
High
Gain
Nice to have
Gain
Undefined
Gain
Very High
good first issue
i18n/backport-stable
impact
large
impact
medium
impact
small
impact
unknown
Incompatible license
issue
closed
issue
do-not-exist-yet
issue
open
manual test
Manually tested during feature freeze
OS
FreeBSD
OS
Linux
OS
macOS
OS
Windows
problem
QA
regression
release blocker
Release Cycle
Feature Freeze
release-blocker
v7.0
release-blocker
v7.0.1
release-blocker
v7.0.2
release-blocker
v7.0.3
release-blocker
v7.0.4
release-blocker
v8.0.0
release-blocker/v9.0.0
run-all-playwright-tests
run-end-to-end-tests
test
manual
test
needed
test
needs-help
test
not-needed
test
present
untested
User research - time-tracker
valuable code
worth a release-note
User research - Accessibility
User research - Blocked
User research - Community
User research - Config (instance)
User research - Errors
User research - Filters
User research - Future backlog
User research - Git workflow
User research - Labels
User research - Moderation
User research - Needs input
User research - Notifications/Dashboard
User research - Rendering
User research - Repo creation
User research - Repo units
User research - Security
User research - Settings (in-app)
No milestone
No project
No assignees
4 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo/forgejo!11381
No description provided.