Skip to main content
Laravel, shipping fast.
Chapter 19 · A Security Review

8. Security Misconfiguration

Julian Beaujardin

Nothing wrong with the code. Something wrong with how it is run.

Here: APP_DEBUG=true in production, which turns every 500 into a page showing file paths, queries, and environment values. CORS left at its open default. The API documentation from Chapter 15 readable from the internet. A .env file served by a misconfigured web server.

What stops it: less of this is automatic than people assume.

  • The .env.example every project starts from has APP_DEBUG=true and APP_ENV=local. Production must set both. Chapter 20 makes the application refuse to serve with debug on anywhere but a developer’s machine.
  • Laravel’s CORS configuration allows every origin on api/* out of the box. Chapter 6 closed it.
  • The default 404 names your model classes. Chapter 7 replaced it.
  • The documentation is behind a Gate, and Chapter 15 said to verify that from outside.

How you know:

php artisan about

Run it in production and read it: environment, debug mode, cache and queue drivers. Then, from outside, request a URL that doesn’t exist and one that throws, and read the responses as an attacker would. If you learn anything about the server from them, so does everyone else.

9. Improper Inventory Management

You can’t protect what you have forgotten you run.

Here: version v1, deprecated and still answering. A staging server with production data and a weaker configuration. A token issued for a migration two years ago. An endpoint added for a demo.

What stops it: Chapter 16 retires versions by deleting them. Chapter 15 generates the documentation from the routes, so an endpoint that exists is an endpoint that is listed. Chapter 4 expires tokens.

How you know: compare three lists: the routes the application has, the routes the documentation shows, and the routes that received traffic last month. Anything in the first and not the third is a candidate for deletion. Anything in the third and not the second is a surprise.

10. Unsafe Consumption of APIs

You trust what a third party sends you more than you would trust a user.

Here: Statamic is, to this API, an input. Its responses are data from outside, and they pass through into your responses.

What stops it: Chapter 3 treated the provider as untrusted from the first line. License::fromProvider() validates every payload and throws MalformedProviderResponse, which Chapter 7 renders as a 502. The driver refuses a response whose data isn’t a list, so an HTML error page can’t pass for “no licenses.” The Resource decides which fields are forwarded, so a new field at the provider doesn’t become a new field in your API. Every call has a timeout, and no provider message is ever repeated to a consumer.

How you know: the test from Chapter 12 in which the provider leaves a field out. Add its cousins: a field of the wrong type, HTML where JSON was expected, a 200 with an empty body. The API should answer each with a 502 and a code, never a 500 and never a 200.

The audio could not be loaded. Try again in a moment.