fix: some bad requests were not logged
Massimo Melina committed
Apr 27, 2026 at 19:27 UTC
33c8335785d0043b1f7a8051ac560a8ab36913c1
3 files changed
+22
-2
src/index.ts
+1
-1
@@ -43,7 +43,6 @@ export const app = new Koa({ keys })
43
app.use(sessionMiddleware)
44
.use(selfCheckMiddleware)
45
.use(acmeMiddleware)
46
- .use(someSecurity)
46
.use(prepareState)
47
.use(geoFilter)
48
.use(trackIpsMw)
@@ -52,6 +51,7 @@ app.use(sessionMiddleware)
51
.use(headRequests)
52
.use(rootsMiddleware)
53
.use(logMw)
54
+ .use(someSecurity)
55
.use(throttler)
56
.use(pluginsMiddleware)
57
.use(mount(API_URI, apiMiddleware({ ...frontEndApis, ...adminApis })))
src/middlewares.ts
+2
-1
@@ -50,7 +50,6 @@ export const headRequests: Koa.Middleware = async (ctx, next) => {
50
let proxyDetected: undefined | Koa.Context
51
export let cloudflareDetected: undefined | Date
52
export const someSecurity: Koa.Middleware = (ctx, next) => {
53
- ctx.request.ip = normalizeIp(ctx.ip)
53
const ss = ctx.session
54
if (ss?.username && !ss?.[ALLOW_SESSION_IP_CHANGE])
55
if (!ss.ip)
@@ -92,6 +91,8 @@ export function getProxyDetected() {
91
}
92
93
export const prepareState: Koa.Middleware = async (ctx, next) => {
94
+ // normalize once so auth, filters and logging agree on the same client address
95
+ ctx.request.ip = normalizeIp(ctx.ip)
96
const s = ctx.session
97
if (s?.username) {
98
if (s.ts < invalidateSessionBefore.get(s?.username)!)
tests/test.ts
+19
@@ -1319,6 +1319,25 @@ describe('admin', () => {
1319
})
1320
})
1321
1322
+describe('logging', () => {
1323
+ test('security-filtered traversal reaches the error log', async () => {
1324
+ const logPath = resolve(__dirname, 'work/logs/access-error.log')
1325
+ const uri = `/f1/page/.%2e/.%2e/README.md?log-test=${randomId(8)}`
1326
+ const adminJar = {}
1327
+ await reqApi('set_config', { values: { dont_log_net: '' } }, 200, { auth, jar: adminJar })()
1328
+ try {
1329
+ await req(uri, 404, { jar: {} })()
1330
+ const found = await waitFor(() =>
1331
+ existsSync(logPath) && readFileSync(logPath, 'utf8').includes(uri))
1332
+ if (!found)
1333
+ throw Error('traversal request was not written to the error log')
1334
+ }
1335
+ finally {
1336
+ await reqApi('set_config', { values: { dont_log_net: '127.0.0.1|::1' } }, 200, { auth, jar: adminJar })()
1337
+ }
1338
+ })
1339
+})
1340
+
1341
function login(usr: string, pwd=password) {
1342
return srpClientSequence(srp, usr, pwd, (cmd: string, params: any) =>
1343
reqApi(cmd, params, (x,res)=> res.statusCode < 400)())