The OWASP Top 10, 2025
Security work without a frame is a list of things you happened to remember. The OWASP Top 10 is the frame most of the industry uses: a ranked list of the categories of weakness that cause breaches, revised every few years from real data.
The current release is 2025, and it is not the list you may have memorized:
| Category | |
|---|---|
| A01:2025 | Broken Access Control |
| A02:2025 | Security Misconfiguration |
| A03:2025 | Software Supply Chain Failures |
| A04:2025 | Cryptographic Failures |
| A05:2025 | Injection |
| A06:2025 | Insecure Design |
| A07:2025 | Authentication Failures |
| A08:2025 | Software or Data Integrity Failures |
| A09:2025 | Security Logging and Alerting Failures |
| A10:2025 | Mishandling of Exceptional Conditions |
Notice two entries before anything else, because they say what has changed about how software gets attacked.
A03, Software Supply Chain Failures, is the old "components with known vulnerabilities" grown into something much larger. It now covers "breakdowns or other compromises in the process of building, distributing, or updating software": your dependencies, but also your CI system, your artifact storage and your own laptop. Lesson 5 is about it. It moved up the list because attacks now target the machines that build software as well as the software itself.
A10, Mishandling of Exceptional Conditions, is new. It covers what happens when your application does not know what to do: errors that fail open, exception messages that leak internals, multi-step operations with no rollback. The document's own summary of it is the sentence to remember: "Any time an application is unsure of its next instruction, an exceptional condition has been mishandled."
What Rails gives you, and what it does not
A large part of this list is handled by the framework if you stay on the paths it provides.
| Category | Rails' contribution |
|---|---|
| A05 Injection | Parameterized queries, escaped views by default |
| A04 Cryptographic Failures | has_secure_password, encrypted credentials, force_ssl |
| A08 Integrity Failures | Signed cookies, Gemfile.lock, CSRF protection |
| A02 Misconfiguration | Sensible production defaults, filter_parameters |
| A01 Broken Access Control | Nothing. This one is entirely yours |
That last row is why A01 is first on the list and why lesson 2 is about it. Rails will happily let a controller load any record by id for any user, because deciding who may see what is a domain question and the framework has no opinion about your domain.
flowchart TB
R["Rails defaults"] --> I["Injection: mostly handled"]
R --> C["Crypto: mostly handled"]
R --> M["Misconfiguration: good defaults, easy to undo"]
R -.->|"nothing"| AC["Access control: entirely yours"]
AC --> D["Your domain policies decide who may do what"]
Where this application already stands
This repository has done several of these deliberately, and they are worth reading as examples rather than as a checklist.
Password policy lives in one place, Auth::PasswordPolicy, with the length bounds and a format requiring lower case, upper case, a digit and a symbol. One definition, used by the model, the view and the strength meter: A07 handled as a design decision instead of three copies that drift apart.
User enumeration is defended against in an unusual and correct way. Identity::User sets the uniqueness message to "is not available" rather than Rails' default "has already been taken":
validates :email_address, uniqueness: { case_sensitive: false, message: "is not available" }
The default message tells an attacker that an address is registered. The replacement does not, and it costs nothing.
Transport is covered by force_ssl, assume_ssl and the secure cookie behavior from the SSL course.
Dependencies get some attention: Dependabot opens update pull requests for gems and GitHub Actions, and CI runs bin/importmap audit on the pinned JavaScript packages. CI's other scanner, bin/brakeman, checks the application's own code, not its dependencies. That is the beginning of A03, not the end of it.
The point of a list
The Top 10 is not a certification and it is not sufficient. What it is good for is coverage: it stops security work from being a list of the things you find interesting, and it gives a team a shared vocabulary for what is worth arguing about.
A useful way to hold it: most breaches are boring. They are missing access checks, a misconfigured default, a dependency nobody updated. The interesting attacks make the news precisely because they are rare, and a team that spends its attention there while shipping a controller without an ownership check has optimized for the wrong distribution.
What this course covers
- The OWASP Top 10, 2025 (this lesson).
- Broken access control, in Rails.
- Injection and its modern shapes.
- Authentication and session handling.
- Supply chain and dependencies.
- Configuration, secrets, and failing safely.
- Putting it together: auditing this application.
Key takeaways
- The current release is the OWASP Top 10:2025, with Broken Access Control first and Security Misconfiguration second.
- A03 is now Software Supply Chain Failures: the whole build and distribution process, well beyond outdated gems.
- A10, Mishandling of Exceptional Conditions, is new: failing open, leaking internals, and operations with no rollback.
- Rails handles much of injection, cryptography and integrity by default; access control it does not handle at all.
- This repository already applies a single password policy and non-enumerating uniqueness messages.
Keep going with lesson 2
Broken access control, in Rails
Shows how to scope queries to the current user, protect admin routes, review permit lists and test refusals.
A free account also gives you the quizzes, your progress and notes, and the discussion.