From 2368c23cc48c5c9e5948dba301f25e3a4e556606 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 2 Aug 2026 17:46:17 +0000 Subject: [PATCH 1/2] feat: add Cloudflare Worker to inject HTTP security headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The site is hosted on GitHub Pages behind Cloudflare. GitHub Pages cannot set custom HTTP response headers, so securityheaders.com gave the site an F. This adds a Cloudflare Worker (cloudflare/worker.js) that attaches the six missing security headers to every response: - Strict-Transport-Security (HSTS, 1-year + preload) - Content-Security-Policy (mirrors the existing HTML meta tag) - X-Frame-Options (SAMEORIGIN) - X-Content-Type-Options (nosniff) - Referrer-Policy (strict-origin-when-cross-origin) - Permissions-Policy (camera/mic/geo/payment/usb disabled) A GitHub Actions workflow (.github/workflows/deploy-worker.yml) deploys the worker automatically on every push to main that touches the cloudflare/ directory. Two repository secrets must be added to activate it: CLOUDFLARE_API_TOKEN — a token with "Edit Workers" permission CLOUDFLARE_ACCOUNT_ID — the Cloudflare account ID Also removes the expired Chrome Prompt API origin-trial meta tag (it expired 24 Mar 2026) from _layouts/default.html. --- .github/workflows/deploy-worker.yml | 29 ++++++++++++++ _layouts/default.html | 3 -- cloudflare/worker.js | 59 +++++++++++++++++++++++++++++ cloudflare/wrangler.toml | 14 +++++++ 4 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/deploy-worker.yml create mode 100644 cloudflare/worker.js create mode 100644 cloudflare/wrangler.toml diff --git a/.github/workflows/deploy-worker.yml b/.github/workflows/deploy-worker.yml new file mode 100644 index 0000000..e27c11c --- /dev/null +++ b/.github/workflows/deploy-worker.yml @@ -0,0 +1,29 @@ +name: Deploy Cloudflare Worker (security headers) + +on: + push: + branches: + - main + paths: + - "cloudflare/**" + workflow_dispatch: + +jobs: + deploy: + name: Deploy worker + runs-on: ubuntu-latest + defaults: + run: + working-directory: cloudflare + + steps: + # actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + + # cloudflare/wrangler-action@v3 + - name: Deploy with Wrangler + uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + workingDirectory: cloudflare diff --git a/_layouts/default.html b/_layouts/default.html index 7f5ed97..592fa63 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -14,9 +14,6 @@ - - - diff --git a/cloudflare/worker.js b/cloudflare/worker.js new file mode 100644 index 0000000..3a992d5 --- /dev/null +++ b/cloudflare/worker.js @@ -0,0 +1,59 @@ +/** + * Cloudflare Worker – adds HTTP security headers to every response. + * + * Deployed via .github/workflows/deploy-worker.yml. + * Required GitHub secrets: + * CLOUDFLARE_API_TOKEN – a token with "Edit Workers" permission + * CLOUDFLARE_ACCOUNT_ID – your Cloudflare account ID + */ + +const SECURITY_HEADERS = { + // Enforce HTTPS for 1 year, include sub-domains, opt into the HSTS preload list + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + + // Prevent browsers from MIME-sniffing away from the declared content-type + "X-Content-Type-Options": "nosniff", + + // Allow framing only from the same origin (defence against clickjacking) + "X-Frame-Options": "SAMEORIGIN", + + // Send only the origin (no path/query) for cross-origin requests + "Referrer-Policy": "strict-origin-when-cross-origin", + + // Restrict access to powerful browser features that the site does not use + "Permissions-Policy": + "camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()", + + // Content Security Policy – mirrors the meta tag already in the HTML layout + // so that both HTTP-header CSP (enforced by the browser before HTML is parsed) + // and the meta tag (fallback) agree on the same policy. + "Content-Security-Policy": [ + "default-src 'self'", + "script-src 'self' https://platform.twitter.com", + "style-src 'self' https://fonts.bunny.net", + "font-src https://fonts.bunny.net", + "img-src 'self' data: https://pbs.twimg.com https://abs.twimg.com", + "frame-src https://open.spotify.com https://platform.twitter.com", + "connect-src 'self' https://syndication.twitter.com", + "object-src 'none'", + "base-uri 'self'", + "form-action 'self'", + ].join("; "), +}; + +export default { + async fetch(request, _env, _ctx) { + const response = await fetch(request); + + const newHeaders = new Headers(response.headers); + for (const [name, value] of Object.entries(SECURITY_HEADERS)) { + newHeaders.set(name, value); + } + + return new Response(response.body, { + status: response.status, + statusText: response.statusText, + headers: newHeaders, + }); + }, +}; diff --git a/cloudflare/wrangler.toml b/cloudflare/wrangler.toml new file mode 100644 index 0000000..524e2ec --- /dev/null +++ b/cloudflare/wrangler.toml @@ -0,0 +1,14 @@ +name = "remotehack-security-headers" +main = "worker.js" +compatibility_date = "2024-01-01" + +# The worker runs on the remotehack.space zone, intercepting every request +# so it can attach security headers to every response before it reaches +# the visitor's browser. +# +# account_id is supplied via the CLOUDFLARE_ACCOUNT_ID environment variable +# in the GitHub Actions deployment workflow – do not hard-code it here. + +[[routes]] +pattern = "remotehack.space/*" +zone_name = "remotehack.space" From f690f16464cf55f47a1e48cb2c02643b0a2e3fd3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 2 Aug 2026 17:47:53 +0000 Subject: [PATCH 2/2] fix: restrict GITHUB_TOKEN permissions in deploy-worker workflow --- .github/workflows/deploy-worker.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/deploy-worker.yml b/.github/workflows/deploy-worker.yml index e27c11c..b7af9d0 100644 --- a/.github/workflows/deploy-worker.yml +++ b/.github/workflows/deploy-worker.yml @@ -12,6 +12,8 @@ jobs: deploy: name: Deploy worker runs-on: ubuntu-latest + permissions: + contents: read defaults: run: working-directory: cloudflare