Skip to content
Merged
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
56 changes: 56 additions & 0 deletions Caddyfile.prod
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,59 @@ api-direct.github-store.org {
output stdout
}
}

# Komi Store paid backend. Hosted on the same VPS, separate Docker service
# (paid-app), separate Postgres database (komistore_paid). Will eventually
# absorb the github-store.org hostnames above once the free-tier migration
# lands; for now the two run side-by-side under distinct vhosts so DNS,
# Stripe webhook URLs, and Cloudflare KV bindings stay decoupled.
#
# DNS prereq: api.komistore.app must resolve to this VPS for Caddy's
# HTTP-01 challenge to issue a Let's Encrypt cert. Either:
# (a) DNS-only (grey-cloud) A record -> VPS IP, OR
# (b) Cloudflare proxied + SSL mode "Full (strict)" + Cloudflare origin
# cert OR DNS-01 challenge configured in Caddy.
# Start with (a) until traffic justifies fronting.
api.komistore.app {
# Direct-to-VPS path (grey-cloud DNS). Overwrite any client-supplied
# X-Forwarded-For with the real TCP source — without this a client who
# forges X-Forwarded-For can rotate past paid-app's rate limiter
# (which keys on X-Forwarded-For's first IP). Same defence as
# api-direct.github-store.org above.
request_header X-Forwarded-For {remote_host}

# Strip any client-supplied CF-Connecting-IP. No Cloudflare hop on this
# vhost yet (grey-cloud); accepting the header would let any client
# claim any source IP. Re-evaluate if/when this vhost goes orange-cloud.
request_header -CF-Connecting-IP

# Body cap. Stripe webhooks can be ~10 KB; checkout payloads are tiny.
# 1 MB matches the free-tier ceiling -- bumps need a written reason.
request_body {
max_size 1MB
}

reverse_proxy paid-app:8080

Comment thread
coderabbitai[bot] marked this conversation as resolved.
header {
-Server
X-Content-Type-Options nosniff
X-Frame-Options DENY
Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
# Looser than the API-only CSP above because the paid backend
# serves /legal HTML pages (terms, privacy) alongside JSON.
# default-src 'none' would block same-origin assets the legal
# pages load (linked stylesheets, images). Note that 'self' does
# NOT permit inline <style>/<script> blocks — those require an
# explicit 'unsafe-inline' in style-src/script-src or a nonce.
# The /legal templates are kept inline-asset-free for that reason.
# frame-ancestors stays locked to prevent clickjack.
Content-Security-Policy "default-src 'self'; frame-ancestors 'none'"
Comment on lines +120 to +128
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

CSP currently contradicts the inline legal-page requirement.

Line 111-Line 112 says /legal uses inline <style>/<script>, but default-src 'self' on Line 113 blocks inline content and can break those pages.

Proposed config adjustment
-        Content-Security-Policy "default-src 'self'; frame-ancestors 'none'"
+        Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; frame-ancestors 'none'"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Looser than the API-only CSP above because the paid backend
# serves the /legal HTML pages (terms, privacy) as well as JSON.
# default-src 'none' would break inline <style>/<script> the legal
# pages use. Keep frame-ancestors locked down to prevent clickjack.
Content-Security-Policy "default-src 'self'; frame-ancestors 'none'"
# Looser than the API-only CSP above because the paid backend
# serves the /legal HTML pages (terms, privacy) as well as JSON.
# default-src 'none' would break inline <style>/<script> the legal
# pages use. Keep frame-ancestors locked down to prevent clickjack.
Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; frame-ancestors 'none'"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Caddyfile.prod` around lines 109 - 113, The CSP header defined by
Content-Security-Policy currently uses default-src 'self' which blocks inline
<style> and <script> used by the /legal pages; update the CSP string to
explicitly allow inline styles and scripts while keeping clickjacking
protection—e.g., add script-src 'self' 'unsafe-inline' and style-src 'self'
'unsafe-inline' (or use nonces if you can modify the pages) and keep
frame-ancestors 'none' so the header in Caddyfile.prod reads with explicit
script-src and style-src allowing inline content for the legal pages.

Comment thread
greptile-apps[bot] marked this conversation as resolved.
Referrer-Policy "no-referrer"
Permissions-Policy "interest-cohort=()"
}

log {
output stdout
}
}
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Loading