mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-08-28 05:27:41 +00:00
fix(server): allow required CSP handoffs
Permit GitHub App manifest form posts and signed HTTPS VNC preview iframes while keeping the rest of the SPA CSP locked down. Mirror the policy in the split-web Caddy config.
This commit is contained in:
parent
4a156d5551
commit
3e881e9938
2 changed files with 16 additions and 5 deletions
|
|
@ -9,7 +9,7 @@
|
||||||
Cross-Origin-Opener-Policy same-origin
|
Cross-Origin-Opener-Policy same-origin
|
||||||
Cross-Origin-Resource-Policy same-origin
|
Cross-Origin-Resource-Policy same-origin
|
||||||
Permissions-Policy "accelerometer=(), autoplay=(), camera=(), display-capture=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), usb=(), web-share=(), xr-spatial-tracking=()"
|
Permissions-Policy "accelerometer=(), autoplay=(), camera=(), display-capture=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), usb=(), web-share=(), xr-spatial-tracking=()"
|
||||||
Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' https://fonts.googleapis.com 'unsafe-inline'; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: blob: https://avatars.githubusercontent.com; connect-src 'self' ws: wss:; worker-src 'self' blob:; manifest-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; object-src 'none'"
|
Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' https://fonts.googleapis.com 'unsafe-inline'; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: blob: https://avatars.githubusercontent.com; connect-src 'self' ws: wss:; worker-src 'self' blob:; frame-src 'self' https:; manifest-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self' https://github.com; object-src 'none'"
|
||||||
}
|
}
|
||||||
|
|
||||||
@sourceMaps path *.map
|
@sourceMaps path *.map
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@
|
||||||
//!
|
//!
|
||||||
//! The policy is built once at server startup from the embedded SPA
|
//! The policy is built once at server startup from the embedded SPA
|
||||||
//! `index.html` so any inline `<script>` hashes don't drift from the
|
//! `index.html` so any inline `<script>` hashes don't drift from the
|
||||||
//! template. Third-party sources are enumerated explicitly — the only
|
//! template. Third-party sources are enumerated explicitly.
|
||||||
//! outside origins the UI depends on today are Google Fonts.
|
|
||||||
|
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
|
@ -91,7 +90,10 @@ fn build_policy_with_hashes(script_hashes: &[String]) -> String {
|
||||||
// interactions. The meaningful XSS protection still comes from the
|
// interactions. The meaningful XSS protection still comes from the
|
||||||
// script-src restrictions above. `ws:`/`wss:` keep the same-origin
|
// script-src restrictions above. `ws:`/`wss:` keep the same-origin
|
||||||
// terminal WebSocket working across browsers that do not treat `'self'`
|
// terminal WebSocket working across browsers that do not treat `'self'`
|
||||||
// as matching WebSocket schemes for connect-src.
|
// as matching WebSocket schemes for connect-src. `frame-src https:`
|
||||||
|
// allows signed sandbox VNC preview iframes from dynamic Daytona preview
|
||||||
|
// hosts. `https://github.com` in form-action allows the install-mode
|
||||||
|
// GitHub App manifest POST handoff.
|
||||||
format!(
|
format!(
|
||||||
"default-src 'self'; \
|
"default-src 'self'; \
|
||||||
script-src 'self'{inline_script_sources} 'wasm-unsafe-eval'; \
|
script-src 'self'{inline_script_sources} 'wasm-unsafe-eval'; \
|
||||||
|
|
@ -100,10 +102,11 @@ fn build_policy_with_hashes(script_hashes: &[String]) -> String {
|
||||||
img-src 'self' data: blob: https://avatars.githubusercontent.com; \
|
img-src 'self' data: blob: https://avatars.githubusercontent.com; \
|
||||||
connect-src 'self' ws: wss:; \
|
connect-src 'self' ws: wss:; \
|
||||||
worker-src 'self' blob:; \
|
worker-src 'self' blob:; \
|
||||||
|
frame-src 'self' https:; \
|
||||||
manifest-src 'self'; \
|
manifest-src 'self'; \
|
||||||
frame-ancestors 'none'; \
|
frame-ancestors 'none'; \
|
||||||
base-uri 'self'; \
|
base-uri 'self'; \
|
||||||
form-action 'self'; \
|
form-action 'self' https://github.com; \
|
||||||
object-src 'none'"
|
object-src 'none'"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -165,6 +168,14 @@ mod tests {
|
||||||
assert!(policy.contains("font-src 'self' https://fonts.gstatic.com"));
|
assert!(policy.contains("font-src 'self' https://fonts.gstatic.com"));
|
||||||
assert!(policy.contains("style-src 'self' https://fonts.googleapis.com 'unsafe-inline'"));
|
assert!(policy.contains("style-src 'self' https://fonts.googleapis.com 'unsafe-inline'"));
|
||||||
assert!(policy.contains("connect-src 'self' ws: wss:"));
|
assert!(policy.contains("connect-src 'self' ws: wss:"));
|
||||||
|
assert!(
|
||||||
|
policy.contains("frame-src 'self' https:"),
|
||||||
|
"signed sandbox VNC previews are embedded from dynamic HTTPS origins"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
policy.contains("form-action 'self' https://github.com"),
|
||||||
|
"GitHub App manifest creation posts directly to github.com"
|
||||||
|
);
|
||||||
assert!(policy.contains("frame-ancestors 'none'"));
|
assert!(policy.contains("frame-ancestors 'none'"));
|
||||||
assert!(policy.contains("object-src 'none'"));
|
assert!(policy.contains("object-src 'none'"));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue