fix: bad encoding in get=list #1234

Massimo Melina committed May 14, 2026 at 15:33 UTC 96e15ca5c0449aa42e9f1ec745b3878312c1ac08
3 files changed +14 -2
src/serveGuiAndSharedFiles.ts
+2 -1
@@ -162,7 +162,8 @@ async function sendFolderList(node: VfsNode, ctx: Koa.Context) {
162 const { URL } = ctx
163 const base = prepend === undefined && baseUrl.get()
164 || URL.protocol + '//' + URL.host + ctx.state.revProxyPath
165 - prepend = base + pathEncode(decodeURI(ctx.path)) // redo the encoding our way, keeping unicode chars unchanged
165 + // redo the encoding our way, keeping unicode chars unchanged. decode each segment separately because decodeURI preserves reserved escapes like %3A, which pathEncode would double-encode
166 + prepend = base + ctx.path.split('/').map(x => pathEncode(safeDecodeURIComponent(x)).replaceAll('/', '%2F')).join('/')
167 }
168 const walker = walkNode(node, { ctx, depth: depth === '*' ? Infinity : Number(depth), parallelizeRecursion: false }) // parallelization produces out-of-order results, and we don't want it like that here
169 ctx.body = asyncGeneratorToReadable(filterMapGenerator(walker, async el => {
tests/config.yaml
+6 -1
@@ -65,10 +65,15 @@ vfs:
65 - name: for-disabled
66 can_list:
67 - disabled_account
68 - - source: ..
68 + - name: tests
69 + source: ..
70 masks:
71 "**/!*.png|files|":
72 can_see: false
73 + children:
74 + - name: "C:"
75 + children:
76 + - source: ../page/gpl.png
77 - name: renameChild
78 can_upload: true
79 children:
tests/test.ts
+6
@@ -148,6 +148,12 @@ describe('basics', () => {
148 test('name encoding', req(FUNNY_NAME_ENCODED, 200))
149 test('name encoding list', reqList('/', { inList: [FUNNY_NAME] }))
150 test('name encoding search', reqList('/', { inList: [FUNNY_NAME] }, { search: FUNNY_NAME }))
151 + test('folder list preserves encoded colon in prepend', req('/tests/C%3A/?get=list&folders=*', data => {
152 + if (!String(data).includes('/tests/C%3A/gpl.png'))
153 + throw Error('missing correctly encoded path in list: ' + data)
154 + if (String(data).includes('/tests/C%253A/'))
155 + throw Error('double encoded path in list: ' + data)
156 + }))
157
158 test('missing perm', reqList('/for-admins/', 401))
159 test('missing perm.file', req('/for-admins/alfa.txt', 401))