oven-sh / bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
https://bun.sh
Other
74.02k stars 2.75k forks source link

Strict-Transport-Security header removed by Bun when using HTTP (containerized Google Cloud Run environment or local) #13228

Open alexbrayko opened 2 months ago

alexbrayko commented 2 months ago

What version of Bun is running?

1.1.22

What platform is your computer?

Darwin 23.5.0 x86_64 i386

What steps can reproduce the bug?

Steps to Reproduce

Example Code (Node.js HTTP)

const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, {
    'Content-Type': 'text/plain',
    'Strict-Transport-Security': 'max-age=63072000; includeSubDomains; preload',
  });
  res.end('Hello, World!');
});

server.listen(3000, () => {
  console.log(`Server is running at http://localhost:3000`);
});

What is the expected behavior?

The HSTS header should be sent by Bun even when using HTTP, as it does with Node.js. This ensures consistency across different environments where the server may serve over HTTP while the platform adds HTTPS.

What do you see instead?

Bun removes the HSTS header when serving over HTTP, which does not align with the behavior in Node.js.

Nodejs response headers

HTTP/1.1 200 OK
Content-Type: text/plain
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Date: Sat, 10 Aug 2024 18:45:51 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Transfer-Encoding: chunked

Bun response headers

HTTP/1.1 200 OK
Content-Type: text/plain
Date: Sat, 10 Aug 2024 18:49:10 GMT
Content-Length: 13

Additional information

I am running a simple HTTP server using Bun that sets the HSTS (HTTP Strict Transport Security) header. However, I noticed that when I run the server locally with Bun, the HSTS header is not being sent in the response. In contrast, running the same code with Node.js results in the HSTS header being correctly included in the response, even when serving over HTTP.

If I switch to using HTTPS with Bun, the HSTS header is sent as expected. However, in my use case, the server needs to serve over HTTP because the environment (e.g., Google Cloud Run) adds HTTPS automatically.

Please let me know if this is intended behavior or a bug. If it's an issue with my setup, any guidance would be appreciated. However, if it's a bug, I hope this can be resolved to maintain consistent behavior with other runtime environments like Node.js.

Jarred-Sumner commented 2 months ago

This was intended behavior because sometimes people directly pass the Response’s headers object from a fetch() call to Bun.serve’s Response without first removing the strict transport security headers, which causes the request to fail to load in browsers

I’m not sure this was a great idea though. Especially in node:http where there is no user-facing Headers object

alexbrayko commented 2 months ago

This was intended behavior because sometimes people directly pass the Response’s headers object from a fetch() call to Bun.serve’s Response without first removing the strict transport security headers, which causes the request to fail to load in browsers

I’m not sure this was a great idea though. Especially in node:http where there is no user-facing Headers object

Thank you for the explanation. I understand the rationale behind removing the HSTS header to prevent issues when passing the Response object directly to Bun.serve. However, I believe this behavior might introduce some inconsistencies, especially for use cases where the server is meant to serve over HTTP, and HTTPS is handled externally (e.g., by platforms like Google Cloud Run).

In my specific case, I'm relying on Bun to serve an HTTP server where the environment adds HTTPS automatically, and preserving the HSTS header is essential. This is a behavior that works as expected in Node.js but not in Bun, which creates challenges for developers who need consistent behavior across different runtimes.

Would it be possible to introduce a configuration option or another mechanism that allows developers to opt-in to preserve the HSTS header when serving over HTTP? This would provide flexibility while maintaining the default behavior for those who may encounter issues.

Thank you for considering this, and I'd appreciate any guidance on how to best handle this situation in the meantime.

alexbrayko commented 2 months ago

@Jarred-Sumner any happy update?

alexbrayko commented 1 month ago

@Jarred-Sumner , this is a security issue that affects all Bun users, whether they realize it or not. Without ensuring Bun is secure and safe to use, it can't be considered production-ready. I'm confident that this would be a relatively easy fix for your team. Would you mind prioritizing it?

frzi commented 1 month ago

Just deployed a Bun webapp on Render. MDN's HTTP Observatory gave it a score of B+ only because of the missing HSTS header. This was very confusing considering my code explicitly sets this header.

Disabling this feature in Bun or perhaps providing developers with more options would be greatly appreciated 😄