Test and operate APIs

Harden API configuration

Disable unused methods and features, restrict content types and CORS, protect documentation, and keep production errors and credentials controlled.

Good code can be undone by bad configuration. The most dangerous settings are usually development conveniences nobody remembered to turn off. Production deserves its own review, separate from the code.

Inventory every layer

Configuration lives in more places than you think. Gateway, proxy, runtime, framework, storage, and cloud settings all have their own defaults. Go through each layer, remove default accounts and sample routes, and put diagnostics and internal schemas behind the access policy their content deserves.

Default accounts and sample routes need a dedicated pass. They ship enabled, they’re documented publicly, and scanners probe for them by name within hours of a deployment going live.

Think about what development mode gives you. Stack traces, wildcard CORS, interactive API docs. Copy those into production and you bypass all the careful application code. The stack trace names your framework and file paths. Permissive CORS lets a hostile page read API responses with a victim’s cookies. A public Swagger UI hands over a complete map of the attack surface.

Probe the effective behavior

Don’t review files. Review what production does. Environment variables, gateway rules, and framework defaults can override the config file you carefully read.

Three probes catch the most common leftovers:

# does production answer methods you never use?
curl -i -X TRACE https://api.example.com/invoices
# want: HTTP/1.1 405 Method Not Allowed

# does CORS reflect arbitrary origins?
curl -i -X OPTIONS https://api.example.com/invoices \
  -H "Origin: https://evil.example" \
  -H "Access-Control-Request-Method: GET"
# want: no Access-Control-Allow-Origin header for unknown origins

# are the interactive docs public?
curl -i https://api.example.com/docs
# want: 401 or 404 in production, or a deliberate decision otherwise

Watch the CORS one. A middleware that reflects whatever Origin it receives back into Access-Control-Allow-Origin is wildcard CORS wearing a disguise. It passes a casual config review, because there’s no * anywhere. It fails this probe.

Check the downstream path too

The gateway terminating HTTPS means little if the hop behind it crosses a shared network in plaintext. Check the connection to the application and to the database:

psql "host=db.internal dbname=invoices sslmode=require" -c "SHOW ssl;"
#  ssl
# -----
#  on

sslmode=require makes the connection fail if TLS isn’t available, so a successful on here means the path is encrypted.

Run the probes after every production deployment and save the results next to the intended configuration. Configuration drifts quietly. A setting gets flipped during an incident, a new gateway rule lands, a framework upgrade changes a default. The probes catch what a review of the files misses.

Try this on your production API: capture the effective settings from the gateway and the application, not the config files. Probe an unused method, a foreign origin, a debug route, and a downstream connection without TLS. Record each denied result.

Lesson completed