Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/deploy-worker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Deploy Cloudflare Worker (security headers)

on:
push:
branches:
- main
paths:
- "cloudflare/**"
workflow_dispatch:

jobs:
deploy:
name: Deploy worker
runs-on: ubuntu-latest
permissions:
contents: read
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
3 changes: 0 additions & 3 deletions _layouts/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@
<link rel="alternate" type="application/rss+xml" title="remotehack - Airquotes The Pocast Airquotes" href="/live/feed/" />
<link rel="alternate" type="application/rss+xml" title="remotehack - Hacks" href="/feed.xml" />

<!-- [EXPIRES 24 MAR 2026] Prompt API origin trial : https://developer.chrome.com/origintrials/#/view_trial/2533837740349325313 -->
<meta http-equiv="origin-trial" content="Ar0t+xzjU+bJSDl6+bCnDs5w+8ahJ+DhXaR9To2o5og/T/nXRBRoSJlX9rKcPNKHk0Dfj/YW4SIb3um+XAuP6QUAAABkeyJvcmlnaW4iOiJodHRwczovL3JlbW90ZWhhY2suc3BhY2U6NDQzIiwiZmVhdHVyZSI6IkFJUHJvbXB0QVBJTXVsdGltb2RhbElucHV0IiwiZXhwaXJ5IjoxNzc0MzEwNDAwfQ==">

<!-- favicon images -->
<link rel="apple-touch-icon" sizes="180x180" href="/assets/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon-32x32.png">
Expand Down
59 changes: 59 additions & 0 deletions cloudflare/worker.js
Original file line number Diff line number Diff line change
@@ -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,
});
},
};
14 changes: 14 additions & 0 deletions cloudflare/wrangler.toml
Original file line number Diff line number Diff line change
@@ -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"