Files
once-campfire/Gemfile
T
Jeremy Daer c860b51109 Take the SSRF address policy from surfguard instead of keeping our own copy (#241)
* Take the SSRF address policy from surfguard instead of keeping our own copy

Four other apps carried this same classification and the five had drifted into
four different ideas of what "internal" means. It now comes from the surfguard
gem, which is their union. resolve and Violation keep their shapes, so the
opengraph callers are unchanged.

Two verdicts change.

SIIT (::ffff:0:0:0/96) is now recognised. It is the third way an IPv4 address
rides inside an IPv6 one and the only one Ruby has no predicate for --
ipv4_mapped?, ipv4_compat?, private?, loopback? and link_local? are all false
for ::ffff:0:a9fe:a9fe, so it fell through to the IPv6 branch unrecognised and
reached the metadata endpoint. Note the extra group: ::ffff:0:0:0/96 is not the
IPv4-mapped ::ffff:0:0/96 the guard already refused, and the two do not overlap.

The RFC 8215 local-use NAT64 block is now refused whole rather than decoded.
Reading its low 32 bits as an embedded IPv4 is only correct for a /96 Pref64;
the block can host any length from /32 to /96 and the position is not
recoverable from the address alone (RFC 6052 2.2), so the decode reads the
wrong octets. It is never globally routed, so refusing it costs nothing. The
well-known /96 is still decoded and re-checked, so DNS64 for public sites on
IPv6-only hosts keeps working.

Resolution moves from Resolv.getaddress to Resolv.getaddresses, so the guard
sees every address a host answers with rather than only the first.

* Distinguish a DNS lookup failure from a private-IP block in the guard

Advance the surfguard pin so resolve_public_ips raises Unresolvable when a
host resolves to nothing and returns an empty list only when it resolves to a
blocked address. The shim lets Unresolvable propagate as a lookup failure --
matching the old Resolv.getaddress behavior -- and reserves Violation for a
resolved-but-blocked address, so a transient DNS miss is no longer reported as
an SSRF attempt.
2026-08-20 01:59:19 -07:00

63 lines
1.2 KiB
Ruby

source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
# Rails
gem "rails", github: "rails/rails", branch: "main"
gem "ostruct"
gem "benchmark"
# Drivers
gem "sqlite3"
gem "redis", "~> 5.4"
# Deployment
gem "puma", "~> 7.2", ">= 7.2.1"
# Jobs
gem "resque", "~> 2.7.0"
gem "resque-pool", "~> 0.7.1"
# Assets
gem "propshaft", github: "rails/propshaft"
gem "importmap-rails", github: "rails/importmap-rails"
# Hotwire
gem "turbo-rails", github: "hotwired/turbo-rails"
gem "stimulus-rails"
# Media handling
gem "image_processing", ">= 1.2"
# Telemetry
gem "sentry-ruby"
gem "sentry-rails"
# Other
gem "bcrypt"
gem "web-push"
gem "rqrcode"
gem "rails_autolink"
gem "geared_pagination"
gem "jbuilder"
gem "net-http-persistent"
gem "surfguard", github: "basecamp/surfguard" # The SSRF address policy behind RestrictedHTTP
gem "kredis"
gem "platform_agent"
gem "thruster"
group :development, :test do
gem "debug"
gem "rubocop-rails-omakase", require: false
gem "bundler-audit", require: false
gem "faker", require: false
gem "brakeman", require: false
end
group :test do
gem "capybara"
gem "mocha"
gem "selenium-webdriver"
gem "webmock", require: false
end