Skip to content

Commit 747abea

Browse files
authored
feat: replace dev_csp compile-time feature with init arg for frontend canister (#3683)
# Motivation Replace the compile-time `dev_csp` Cargo feature flag on `internet_identity_frontend` with a runtime `dev_csp: opt bool` installation argument. Previously, building the frontend with a relaxed Content Security Policy (allowing HTTP connections for local development) required compiling a separate wasm with `--features dev_csp`. This meant release builds could not be reused for local testing without rebuilding. Now, the same wasm binary can serve both production and development by passing `dev_csp = opt true` in the canister init arg. When enabled: - `connect-src` allows `http:` in addition to `https:` - `upgrade-insecure-requests` directive is omitted When omitted or set to `false`, the strict production CSP is used. # Changes - Add `dev_csp: Option<bool>` to `InternetIdentityFrontendArgs` (Rust) - Add `dev_csp : opt bool` to `InternetIdentityFrontendInit` (Candid) - Replace `#[cfg(feature = "dev_csp")]` checks in `main.rs` with runtime boolean threaded through the CSP construction - Remove `[features]` section from frontend `Cargo.toml` - Remove `II_DEV_CSP` handling from `scripts/build` for frontend - Remove `II_DEV_CSP=1` from frontend build command in `dfx.json` - Add `dev_csp = opt true` to `local_test_arg.did` | [Next PR](#3685) >
1 parent 36d1ef7 commit 747abea

File tree

7 files changed

+27
-24
lines changed

7 files changed

+27
-24
lines changed

dfx.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"type": "custom",
55
"candid": "src/internet_identity_frontend/internet_identity_frontend.did",
66
"wasm": "internet_identity_frontend.wasm.gz",
7-
"build": "bash -c 'II_DEV_CSP=1 II_FETCH_ROOT_KEY=1 II_DUMMY_CAPTCHA=${II_DUMMY_CAPTCHA:-1} scripts/build --frontend'",
7+
"build": "bash -c 'II_FETCH_ROOT_KEY=1 II_DUMMY_CAPTCHA=${II_DUMMY_CAPTCHA:-1} scripts/build --frontend'",
88
"init_arg_file": "src/internet_identity_frontend/local_test_arg.did",
99
"shrink": false
1010
},

scripts/build

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -318,13 +318,6 @@ function build_internet_identity_frontend() {
318318
# WARNING: this MUST be opt-in, because we DO NOT want this in production.
319319
extra_build_args=()
320320

321-
# This enables the "dev_csp" feature which weakens the content security policy to facilitate development.
322-
# WARNING: this MUST be opt-in, because we DO NOT want this in production.
323-
if [ "${II_DEV_CSP:-}" == "1" ]
324-
then
325-
echo "USING DEV CONTENT SECURITY POLICY"
326-
extra_build_args+=( --features dev_csp )
327-
fi
328321
# XXX: for bash > 4.4, empty arrays are considered unset, so do some substitution
329322
build_canister "internet_identity_frontend" ${extra_build_args[@]+"${extra_build_args[@]}"}
330323
}

src/internet_identity_frontend/Cargo.toml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,4 @@ ic-cdk-timers.workspace = true
3030
[dev-dependencies]
3131
candid_parser.workspace = true
3232

33-
[features]
34-
# The dev_csp feature weakens the CSP in order to facilitate development with a locally deployed II instance.
35-
# In particular, this allows
36-
# * accessing II using http instead of https
37-
# * II to connect to localhost both on http and https, which is useful when developing a vc issuer
38-
dev_csp = []
33+

src/internet_identity_frontend/internet_identity_frontend.did

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type InternetIdentityFrontendInit = record {
5454
fetch_root_key : opt bool;
5555
analytics_config : opt opt AnalyticsConfig;
5656
dummy_auth : opt opt DummyAuthConfig;
57+
dev_csp : opt bool;
5758
};
5859

5960
service : (InternetIdentityFrontendInit) -> {

src/internet_identity_frontend/local_test_arg.did

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@
88
fetch_root_key = null;
99
analytics_config = null;
1010
dummy_auth = null;
11+
dev_csp = opt true;
1112
},
1213
)

src/internet_identity_frontend/src/main.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ fn post_upgrade(args: InternetIdentityFrontendArgs) {
3838
fn certify_all_assets(args: InternetIdentityFrontendArgs) {
3939
let static_assets = get_static_assets(&args);
4040
let related_origins = args.related_origins.as_ref();
41+
let dev_csp = args.dev_csp.unwrap_or(false);
4142

4243
// 2. Extract integrity hashes for inline scripts from HTML files
4344
let integrity_hashes = static_assets
@@ -84,6 +85,7 @@ fn certify_all_assets(args: InternetIdentityFrontendArgs) {
8485
headers: get_asset_headers(
8586
integrity_hashes.clone(),
8687
related_origins,
88+
dev_csp,
8789
vec![(
8890
"cache-control".to_string(),
8991
NO_CACHE_ASSET_CACHE_CONTROL.to_string(),
@@ -120,6 +122,7 @@ fn certify_all_assets(args: InternetIdentityFrontendArgs) {
120122
headers: get_asset_headers(
121123
integrity_hashes.clone(),
122124
related_origins,
125+
dev_csp,
123126
vec![headers],
124127
),
125128
fallback_for: vec![],
@@ -144,6 +147,7 @@ fn certify_all_assets(args: InternetIdentityFrontendArgs) {
144147
fn get_asset_headers(
145148
integrity_hashes: Vec<String>,
146149
related_origins: Option<&Vec<String>>,
150+
dev_csp: bool,
147151
additional_headers: Vec<HeaderField>,
148152
) -> Vec<HeaderField> {
149153
let credentials_allowlist = if let Some(related_origins) = related_origins {
@@ -176,7 +180,7 @@ fn get_asset_headers(
176180
// Comprehensive policy to prevent XSS attacks and data injection
177181
(
178182
"Content-Security-Policy".to_string(),
179-
get_content_security_policy(integrity_hashes, related_origins),
183+
get_content_security_policy(integrity_hashes, related_origins, dev_csp),
180184
),
181185
// Strict-Transport-Security (HSTS)
182186
// Forces browsers to use HTTPS for all future requests to this domain
@@ -279,12 +283,14 @@ fn get_asset_headers(
279283
fn get_content_security_policy(
280284
integrity_hashes: Vec<String>,
281285
related_origins: Option<&Vec<String>>,
286+
dev_csp: bool,
282287
) -> String {
283-
let connect_src = "'self' https:";
284-
285-
// Allow connecting via http for development purposes
286-
#[cfg(feature = "dev_csp")]
287-
let connect_src = format!("{connect_src} http:");
288+
let connect_src = if dev_csp {
289+
// Allow connecting via http for development purposes
290+
"'self' https: http:".to_string()
291+
} else {
292+
"'self' https:".to_string()
293+
};
288294

289295
// Build script-src with integrity hashes if provided
290296
let script_src = if integrity_hashes.is_empty() {
@@ -326,10 +332,11 @@ fn get_content_security_policy(
326332

327333
// For production builds, upgrade all HTTP connections to HTTPS
328334
// Omitted in dev builds to allow localhost development
329-
#[cfg(not(feature = "dev_csp"))]
330-
let csp = format!("{csp}upgrade-insecure-requests;");
331-
332-
csp
335+
if !dev_csp {
336+
format!("{csp}upgrade-insecure-requests;")
337+
} else {
338+
csp
339+
}
333340
}
334341

335342
/// Gets the static assets with HTML fixup and well-known endpoints

src/internet_identity_interface/src/internet_identity/types.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,11 @@ pub struct InternetIdentityFrontendArgs {
219219
pub fetch_root_key: Option<bool>,
220220
pub analytics_config: Option<Option<AnalyticsConfig>>,
221221
pub dummy_auth: Option<Option<DummyAuthConfig>>,
222+
/// Weakens the Content Security Policy to facilitate local development over HTTP.
223+
/// When enabled:
224+
/// * allows accessing II using http instead of https
225+
/// * allows II to connect to localhost on both http and https
226+
pub dev_csp: Option<bool>,
222227
}
223228

224229
impl From<InternetIdentityFrontendArgs> for InternetIdentityInit {
@@ -230,6 +235,7 @@ impl From<InternetIdentityFrontendArgs> for InternetIdentityInit {
230235
analytics_config,
231236
dummy_auth,
232237
related_origins,
238+
dev_csp: _,
233239
} = value;
234240

235241
Self {

0 commit comments

Comments
 (0)