Wallarm's api-firewall validates traffic against your own OpenAPI spec
Fast and light-weight API proxy firewall for request and response validation by OpenAPI specs.
At a glance
- What is it?
- api-firewall is an MPL-2.0 licensed Go reverse proxy that accepts only the requests and responses described by an OpenAPI 3.0 or GraphQL schema, and it can run in three shapes: proxying to the backend, validating single requests in API mode, or checking GraphQL over HTTP and WebSocket. It is built on fasthttp and the Coraza WAF engine, and the last push was on 2026-04-03 with release v0.9.6.
- Who is it for?
- Adopt api-firewall when you have a real API specification and need to enforce it in front of the backend, especially to find undocumented endpoints or to catch responses that leak data. Do not adopt it as a general web application firewall, since the OWASP ModSecurity rules are an addition to schema validation rather than a replacement for it, and expect to keep the specification in step with the code.
- Can I use it commercially?
- Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A positive security model driven by the specification
The idea behind api-firewall is that the specification itself is the rule set. When the firewall starts, you provide the REST or GraphQL API specification of the application to be protected, and it operates as a reverse proxy validating whether requests and responses match the schema defined there.
Traffic that does not match the schema is logged using the STDOUT and STDERR Docker services, or blocked, depending on the configured operation mode. The README calls this a positive security model: by allowing you to set the traffic requirements with the API specification, the firewall allows calls that match a predefined specification and rejects everything else.
The distinction from a signature based firewall is worth making explicit. A request that looks strange but is permitted by the schema passes. A request that looks entirely ordinary but is not in the schema fails. That is a much stronger contract for an API, where the schema is usually the source of truth already, and it is why the tool fits the cloud-native environments the README describes it as designed for.
The project is written in Go and uses the fasthttp proxy, and the README says it is optimized for extreme performance and near-zero added latency. It is published on DockerHub and licensed under MPL-2.0, which is a file-level copyleft licence: modifications to the covered files must be published under the same terms, while combining it with other code in a larger work does not force that work under the MPL. This is a description of the terms rather than legal advice.
The last push was on 2026-04-03, and the release published the same day was v0.9.6, following v0.9.5 in December 2025 and v0.9.4 at the end of November 2025.
Three operating modes decide how much traffic reaches the backend
The firewall has three operating modes, and the difference between them is whether the firewall sits in the traffic path and whether it forwards.
In PROXY mode it validates HTTP requests and responses against OpenAPI 3.0 and proxies matching requests to the backend. This is the full deployment: the firewall is a reverse proxy, so it sees both directions of the exchange and can reject a malformed response as well as a malformed request.
In API mode it validates individual requests against OpenAPI 3.0 without further proxying. Nothing is forwarded, which makes it a component you call rather than a component you deploy in front of the backend. That shape suits a service that wants to check a request it has already received, or an integration test harness that wants to know whether a payload would pass.
The third mode, graphql, validates HTTP and WebSocket requests against a GraphQL schema and proxies matching requests to the backend. WebSocket support matters for GraphQL, because subscriptions run over a persistent connection rather than a request and response cycle, so the schema validation has to work on a different transport.
The three modes also mean three different deployment shapes, and the README links a separate installation guide for each: a Docker container guide for REST, an API mode guide and a GraphQL container guide. The GraphQL validation is backed by a Go GraphQL library in the dependency list, while REST validation uses a Go OpenAPI parser.
Logging mode finds the endpoints your specification forgot
The two use cases in the README split along the same line as blocking and logging, and the second one is arguably the more interesting.
In blocking mode, the firewall blocks malicious requests that do not match the specification, and blocks malformed API responses to stop data breaches and sensitive information exposure. The response part is the one that distinguishes this from a request filter, since an API can leak data by returning fields nobody asked for, and a request-side filter would never notice.
In monitoring mode, the firewall logs malformed requests and responses that do not match the specification, and it discovers shadow APIs and undocumented API endpoints. The README describes these as endpoints that are not covered in the API specification but respond to requests, except for endpoints returning the code 404. So the discovery mechanism is empirical: send traffic, see which undocumented paths answer, and log them.
That combination makes monitoring mode a practical first step for most teams. A specification is a document, and documents drift from the code. Running the firewall in logging mode against live traffic shows you both the requests that violate the spec and the endpoints that exist without being in it, which is a two for one exercise in finding out where your documentation and your implementation disagree.
The result is a set of findings you can act on in two directions, since each violation is either a request the client is sending wrongly or a piece of the specification that needs updating. The README's framing of a positive security model only pays off if the specification is accurate, and logging mode is how you find out whether it is.
Request validation covers a wide range of content types
The firewall inspects the body, so the set of content types it understands matters as much as the schema validation itself. The README lists the Content-Type header values it recognises while processing incoming requests.
The JSON, XML and YAML types are the obvious ones, alongside form-urlencoded bodies and multipart form data, which is what a form posting to an API looks like on the wire. The less obvious entries are the binary and text formats: application/octet-stream, application/zip, text/csv and text/plain.
The structured syntax suffixes are the interesting part of the list. The firewall recognises the +json, +xml, +yaml and +csv suffixes, which are the way media types declare that a body is a given format inside another format. A vendor specific type such as application/vnd.example+json is JSON underneath, and a validator that only looked for application/json would treat it as an opaque blob. Handling the suffix means those bodies are validated against the schema rather than skipped.
The dependency list explains how that is done rather than left as a claim. There is a fast JSON parser and a fast XML parser in the Go module, a YAML library, a MIME type detection library, and a Brotli and general compression library, alongside a Go validator library for struct level checks. XML is handled through a struct to XML mapper, which is what makes validation of a WSDL style or XML schema payload possible at all rather than merely tolerated.
Beyond schemas: tokens, denylists, IP lists and ModSecurity
Schema validation is the core, but the feature list in the README covers several more layers that a real deployment needs.
On authentication, the firewall validates JWT access tokens for OAuth 2.0 protocol based authentication, which means an invalid or expired token is rejected at the edge rather than by each backend service. Alongside that it can denylist compromised API tokens, keys and cookies, so that a credential which leaked can be blocked centrally without redeploying the services that use it. The AllowIPList feature restricts access to endpoints by defining a list of allowed IP addresses.
For payload inspection beyond the schema, the firewall supports ModSecurity Rules and the OWASP ModSecurity Core Rule Set. The Go dependency list shows this is built on Coraza, with the ModSecurity compatible engine and its libinjection helper listed, and the WAF integration is therefore a real rule engine rather than a regex pass bolted on afterwards.
The two philosophies sit together with some tension, and it is fair to say so. Schema validation knows what is allowed, while the ModSecurity rules know what patterns have historically been used in attacks. A request can satisfy the schema and still match an attack rule, and a request can be benign and fail the schema. Which one wins depends on how the rules are configured, and the README does not document that precedence, so it is worth reading the deployment guide for the version you use before turning blocking on.
Observability is handled with a Prometheus client library and structured logging through a Go logging library, and the repository carries a Helm chart directory, so metrics and container orchestration are part of the distribution rather than something you assemble.
fasthttp, and the benchmark numbers to read carefully
The performance claim is stated in the README, and the raw output is included, which is more useful than a summary figure.
The headline number is that the average time required for the firewall to process one request is 1.339 milliseconds, described as 66 percent faster than Nginx. The supporting output compares the firewall with JSON validation against Nginx without JSON validation, using the ApacheBench tool with 200 concurrent connections and 10000 requests against a large JSON payload:
$ ab -c 200 -n 10000 -p ./large.json -T application/json http://127.0.0.1:8282/test/signup
Requests per second: 13005.81 [#/sec] (mean)
Time per request: 15.378 [ms] (mean)
Time per request: 0.077 [ms] (mean, across all concurrent requests)The same run against Nginx 1.18.0 reports 7887.76 requests per second, 25.356 milliseconds per request, and 0.127 milliseconds across concurrent requests.
Two cautions on reading this. The comparison is not like for like, because the firewall is doing JSON schema validation and Nginx is not, so the firewall is doing more work and still coming out ahead. And these are mean figures from a single local run on one machine, with the version noted as API Firewall 0.6.2 rather than the current release, so the numbers describe the project's approach rather than the build you would deploy.
The design reason for the speed is in the stack rather than in tuning. The HTTP layer is fasthttp, which is built for proxy workloads, and the JSON and XML handling uses the fast parsers listed earlier, so validation is not a second full parse of a body the server already read.
Building, running and testing the firewall
The repository is a Go project with a Makefile, a Dockerfile, a Helm chart and demo environments, and the tooling tells you how the project is developed.
The Dockerfile is a three stage build. The first stage compiles the binary on an Alpine Go image and passes the version through linker flags, and it does something worth copying: after the build it runs the binary with a version flag as a smoke test, so a broken image fails at build time rather than at deploy time. The final stage creates a dedicated unprivileged user with a fixed user id and runs the entrypoint script as that user, so the container does not need root.
The Makefile builds the image with the version and namespace passed as build arguments, and the version is pinned in one place, 0.9.6, matching the namespace github.com/wallarm/api-firewall. The test target runs the Go tests with the race detector and coverage, and excludes tests whose names start with W, which is a convention for the tests that need a network or a running backend. There is a separate bench target that runs the WebSocket GraphQL benchmark with one and with four processors so you can see the scaling.
There are also the operational checks a security tool should have. A lint target runs golangci-lint, a vulncheck target runs govulncheck over the dependency tree, and a load test target brings up a compose file and runs a k6 scenario against it, with the images pulled from Docker Hub.
For evaluation without writing any code, the repository ships demo environments, one with Docker Compose and one with Kubernetes, each deploying an example application protected by the firewall. Those are the fastest way to see the blocking and logging behaviour on real traffic before you put it in front of anything you care about.
Editorial conclusion
Adopt api-firewall when you have a real API specification and need to enforce it in front of the backend, especially to find undocumented endpoints or to catch responses that leak data. Do not adopt it as a general web application firewall, since the OWASP ModSecurity rules are an addition to schema validation rather than a replacement for it, and expect to keep the specification in step with the code. Verify first by running it in logging mode against a copy of production traffic, because a blocking deployment that rejects a valid request your specification never described will take the API down rather than merely log it.
Frequently asked questions
What operating modes does Wallarm's api-firewall support?
Three. PROXY validates HTTP requests and responses against OpenAPI 3.0 and proxies matching requests to the backend, API validates individual requests against OpenAPI 3.0 without proxying, and the graphql mode validates HTTP and WebSocket requests against a GraphQL schema and proxies matching requests onward.
How does api-firewall find undocumented API endpoints?
In monitoring mode it logs malformed requests and responses that do not match the specification, and it records shadow API endpoints, which the README defines as endpoints not covered in the API specification that respond to requests, excluding any that return a 404.
Does api-firewall need to sit in front of the backend to work?
Not always. In API mode it validates individual requests against OpenAPI 3.0 without further proxying, so it can be used as a component that checks requests a service has already received. Only the PROXY and graphql modes forward traffic to the backend.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/wallarm-api-firewall)Was this useful?