Skip to content

Commit b5aa8ad

Browse files
committed
fix: constrain the chapter catch-all route to the slug alphabet
Chapter slugs come from name.parameterize, which produces lowercase letters, digits, hyphens, and underscores (parameterize preserves underscores via its gsub). Constraining the catch-all (:id => 'chapter#show') to that alphabet makes paths with dots, uppercase, or other characters 404 at the router instead of reaching ChapterController and the database. format: false stops Rails from consuming a trailing .pem as an optional format segment. Most of this traffic is scanner junk: on 2026-09-16, 91% of the 4,218 ChapterController requests were 404s, mostly sensitive-file probes. Underscore paths still route and 404 in-app with the branded page. Production slug audit (2026-09-19): 54 chapters, 0 slugs outside [a-z0-9_-]+. Closes #2891
1 parent 11bc410 commit b5aa8ad

2 files changed

Lines changed: 26 additions & 1 deletion

File tree

config/routes.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@
201201
get 'donate' => 'pages#show', id: 'donate'
202202
get 'codebar-stories-podcast' => 'pages#show', id: 'codebar-stories-podcast'
203203

204-
get ':id' => 'chapter#show', as: :chapter
204+
get ':id' => 'chapter#show', as: :chapter, format: false, constraints: { id: /[a-z0-9_-]+/ }
205205

206206
# Redirects
207207
get '/my/jobs/new', to: redirect('https://jobs.codebar.io/my/jobs/new')
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# frozen_string_literal: true
2+
3+
require 'rails_helper'
4+
5+
RSpec.describe 'chapter catch-all route' do
6+
it 'routes a chapter slug to chapter#show' do
7+
expect(get: '/london').to route_to(controller: 'chapter', action: 'show', id: 'london')
8+
end
9+
10+
# Chapter#set_slug builds slugs with name.parameterize, which produces
11+
# lowercase letters, digits, hyphens, and underscores.
12+
it 'routes every character class the slug generator can produce' do
13+
expect(get: '/123').to route_to(controller: 'chapter', action: 'show', id: '123')
14+
expect(get: '/south-london').to route_to(controller: 'chapter', action: 'show', id: 'south-london')
15+
expect(get: '/spring_wildcats').to route_to(controller: 'chapter', action: 'show', id: 'spring_wildcats')
16+
end
17+
18+
it 'does not route paths containing dots' do
19+
expect(get: '/key.pem').not_to be_routable
20+
end
21+
22+
it 'does not route paths containing uppercase characters' do
23+
expect(get: '/Shanghai').not_to be_routable
24+
end
25+
end

0 commit comments

Comments
 (0)