Dev.to · 5 min read

Five findings in FastAPI, and what happened when I reported them

Five findings in FastAPI, and what happened when I reported them

An introduction to a short series. Four of the five are still live in the current release, and each post carries a reproduction you can run. I use FastAPI. In July, I went looking through it because I wanted to know what I was running in production. I found five things. I reported all five privately on 26 July 2026, through GitHub's private vulnerability reporting, which is the channel the project asks you to use. On 11 August, all five were closed without publication. Three days after I filed them, the maintainer fixed one of them himself. This series is the write-up. One post per finding, published over this and next week, then a closing essay. Each post contains a reproduction, permalinks to the exact code pinned to a release tag, the argument for why I think it's a defect, and the argument against my own finding because several of these are genuinely arguable, and a write-up that hides that isn't worth reading. Before you read the findings: how this project handles security This context matters, and it isn't an accusation. It's the thing that makes everything else in the series legible. I went looking for FastAPI's advisory history across every database that carries Python vulnerabilities, OSV.dev, the PyPA advisory database, and the GitHub Advisory Database. They agree: Advisory Date Where the defect was CVE-2021-32677 2021-06-09 FastAPI's own code — CSRF via content-type handling CVE-2024-24762 2024-02-05 python-multipart — a ReDoS FastAPI users inherited That's the complete list. Two records, one of which is a dependency's flaw that FastAPI users needed to act on. FastAPI's release notes tell the same story from the other side. The heading "Security fixes" appears three times in the project's entire history: 0.65.1 (a Pydantic version pin), 0.65.2 (the CSRF fix above), and 0.109.1 (the python-multipart pin). So: one published advisory for a defect in FastAPI's own code, in June 2021. Five years and two months ago. I don't think that means five years of silently sitting on vulnerabilities. I think it means the project fixes things as ordinary bugs and reserves advisories for almost nothing. That's a legitimate policy choice, an unusual one, but defensible, and made consistently for years. It's also the single most useful fact for interpreting what happened to my reports. Measured against that baseline, five declined advisories are not an anomaly. It's the norm operating exactly as it has since 2021. The one that was fixed On 26 July, I reported that FastAPI's frontend() helper ran its authentication dependencies and then discarded everything they set — headers, Set-Cookie, status changes, background tasks. The feature had been shipped two weeks earlier, advertised as "automatic cookie authentication for the frontend." The cookie rotation was built to silently vanish. On 29 July, PR #16105 -> "🐛 Fix support for background tasks and headers from dependencies in app.frontend()" — was authored by tiangolo, labeled bug, and merged. It shipped in 0.141.1. The current code does exactly what the report asked for in the function the report named. On 11 August, the report was closed as not accepted. I don't know whether my report caused that fix. The PR doesn't reference it, and I wasn't told either way. What I can say is that they describe the same defect in the same function, three days apart. I want to be clear about how I read that, because it's not the reading you might expect: that looks like collaboration to me. Something was broken; it got reported; it got fixed fast, and users are better off. That's the system working. The part I found hard was that the collaboration was never acknowledged as such. What's in the series Post Finding Status on 0.141.1 1 jsonable_encoder returns the contents of Pydantic's Secret[T] Unfixed 2 response_model on a streaming route is accepted and ignored Unfixed 3 Json[T] bypasses the documented strict content-type guarantee Unfixed 4 root_path reflected unescaped into the Swagger UI and ReDoc pages Unfixed 5 The one they fixed — frontend() dropping dependency response effects Fixed in 0.141.1 6 Closing essay — what security research looks like when both sides use AI — Every code status was re-verified against FastAPI 0.141.1 on 12 August 2026 by reading the source and running the reproductions, not carried over from the original reports. Where the original reports were wrong, the posts say so. One of them was. On publishing this The findings were disclosed privately first and closed without fixes. Publishing after a decline is standard practice, and I'm not holding anything back that a reader would need to protect themselves. Every post ends with a section on what you can do today, because four of these are live in the version you're probably running. Two of the five I'd characterize as clear framework defects. Two are arguable. One: the documentation page injection. I think it splits the fault between the framework and the deployment, and I say so in the post before the reproduction, rather than after. If you only read one, read the first. It's the one where I think the counterargument is weakest, and it has a one-line fix. Next: the encoder that reaches past a masking primitive and returns the value it was hiding.

This is a summary aggregated from Dev.to. Read the complete article on the original site:

Read full article at Dev.to

More Cybersecurity News