Failed auth attempts are silently dropped — no structured log entry, no forensic trail. Impossible to distinguish a misconfigured client from a brute-force attempt after the fact.
File:internal/auth/bearer.go:22-42
Suggestion: On every 401, emit a structured log line with:
First 8 chars of the presented token (enough to correlate client, not enough to reconstruct)
Timestamp
Failed auth attempts are silently dropped — no structured log entry, no forensic trail. Impossible to distinguish a misconfigured client from a brute-force attempt after the fact.
**File:** `internal/auth/bearer.go:22-42`
**Suggestion:** On every 401, emit a structured log line with:
- Failure reason (`jwt_invalid`, `jwt_dex_unavailable`, `static_token_mismatch`, `no_token`)
- Remote IP
- Token type attempted (JWT vs static)
- First 8 chars of the presented token (enough to correlate client, not enough to reconstruct)
- Timestamp
Done — the bearer auth now lives in the shared mcp-chassis (v0.3.0), adopted by gitea-mcp v0.5.0.
BearerMiddleware emits a structured slog line on every rejection:
reason — one of no_token / static_token_mismatch / jwt_invalid / jwt_dex_unavailable
remote — client IP (X-Forwarded-For aware, falls back to transport peer)
token_type — jwt (three dotted segments) vs opaque vs none
token_fp — a truncated SHA-256 fingerprint of the token
status, path; slog adds the timestamp
Security deviation from the ticket (flagging it): the issue suggested logging the first 8 chars of the raw token. I logged a hashed fingerprint instead — gitea-mcp's own secret-handling rule is that logs flow to stdout→k8s→brain ingestion, so a raw prefix of a static bearer would leak secret entropy into searchable storage. The hash still correlates repeated attempts from one client ("enough to correlate, not to reconstruct") without that risk. If you'd rather have the literal prefix, say so and I'll switch it.
Wired via slog.SetDefault in gitea-mcp so the lines use its JSON handler. Tests: TestBearerMiddleware_AuditLogsRejection asserts the fields present and the raw token absent. Implemented in mcp-chassis (feat commit + v0.3.0 tag).
Done — the bearer auth now lives in the shared `mcp-chassis` (v0.3.0), adopted by gitea-mcp v0.5.0.
`BearerMiddleware` emits a structured `slog` line on **every** rejection:
- `reason` — one of `no_token` / `static_token_mismatch` / `jwt_invalid` / `jwt_dex_unavailable`
- `remote` — client IP (X-Forwarded-For aware, falls back to transport peer)
- `token_type` — `jwt` (three dotted segments) vs `opaque` vs `none`
- `token_fp` — a truncated SHA-256 fingerprint of the token
- `status`, `path`; slog adds the timestamp
**Security deviation from the ticket (flagging it):** the issue suggested logging the *first 8 chars of the raw token*. I logged a **hashed fingerprint** instead — gitea-mcp's own secret-handling rule is that logs flow to stdout→k8s→brain ingestion, so a raw prefix of a **static** bearer would leak secret entropy into searchable storage. The hash still correlates repeated attempts from one client ("enough to correlate, not to reconstruct") without that risk. If you'd rather have the literal prefix, say so and I'll switch it.
Wired via `slog.SetDefault` in gitea-mcp so the lines use its JSON handler. Tests: `TestBearerMiddleware_AuditLogsRejection` asserts the fields present and the raw token absent. Implemented in mcp-chassis (feat commit + v0.3.0 tag).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Failed auth attempts are silently dropped — no structured log entry, no forensic trail. Impossible to distinguish a misconfigured client from a brute-force attempt after the fact.
File:
internal/auth/bearer.go:22-42Suggestion: On every 401, emit a structured log line with:
jwt_invalid,jwt_dex_unavailable,static_token_mismatch,no_token)Done — the bearer auth now lives in the shared
mcp-chassis(v0.3.0), adopted by gitea-mcp v0.5.0.BearerMiddlewareemits a structuredslogline on every rejection:reason— one ofno_token/static_token_mismatch/jwt_invalid/jwt_dex_unavailableremote— client IP (X-Forwarded-For aware, falls back to transport peer)token_type—jwt(three dotted segments) vsopaquevsnonetoken_fp— a truncated SHA-256 fingerprint of the tokenstatus,path; slog adds the timestampSecurity deviation from the ticket (flagging it): the issue suggested logging the first 8 chars of the raw token. I logged a hashed fingerprint instead — gitea-mcp's own secret-handling rule is that logs flow to stdout→k8s→brain ingestion, so a raw prefix of a static bearer would leak secret entropy into searchable storage. The hash still correlates repeated attempts from one client ("enough to correlate, not to reconstruct") without that risk. If you'd rather have the literal prefix, say so and I'll switch it.
Wired via
slog.SetDefaultin gitea-mcp so the lines use its JSON handler. Tests:TestBearerMiddleware_AuditLogsRejectionasserts the fields present and the raw token absent. Implemented in mcp-chassis (feat commit + v0.3.0 tag).