Hmbown/CodeWhale · error

generated mobile cookie is a valid header

Error message

generated mobile cookie is a valid header

What it means

Same family as the Location expect: the handler sets a Set-Cookie header from `mobile::mobile_session_cookie(...)` and asserts via expect that the cookie string is a valid header value. `HeaderValue::from_str` fails only on control characters, so a panic means the generated cookie (session cookie content) contains illegal bytes such as newline or carriage return.

Solutions

  1. Sanitize/validate the session cookie value inside mobile_session_cookie before formatting
  2. Reject control characters when loading the session cookie from the store
  3. Swap expect for a controlled 500 response so a bad cookie cannot panic the worker
  4. Test mobile_session_cookie against values containing \r, \n, and non-ASCII bytes

Example fix

// before
HeaderValue::from_str(&cookie).expect("generated mobile cookie is a valid header")
// after
HeaderValue::from_str(&cookie).unwrap_or_else(|_| {
    tracing::error!("invalid mobile cookie header");
    HeaderValue::from_static("codewhale_mobile=")
})
Defensive patterns

Strategy: validation

Validate before calling

// rust
fn cookie_is_safe(c: &str) -> bool {
    !c.is_empty() && c.bytes().all(|b| (33..=126).contains(&b))
}
// check before insert:
assert!(cookie_is_safe(&cookie));

Type guard

// rust
fn safe_cookie(s: &str) -> Option<HeaderValue> {
    HeaderValue::from_str(s).ok()
}

Try / catch

// rust
if let Ok(v) = HeaderValue::from_str(&cookie) {
    response.headers_mut().insert(header::SET_COOKIE, v);
} else {
    tracing::error!("invalid mobile cookie");
    return StatusCode::INTERNAL_SERVER_ERROR.into_response();
}

Prevention

When it happens

Trigger: `mobile_session_cookie` returns a cookie containing control characters — usually because the underlying session cookie value was corrupted, truncated mid-token, or constructed by concatenating unvalidated input.

Common situations: Upstream session store returning tainted values, manual cookie string manipulation, CRLF injection attempts reaching cookie construction, encoding bugs after a cookie format change.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/9b3e5c2c4ccba7e4. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/runtime_api.rs:1406

        }
        Err(mobile::BootstrapError::Invalid | mobile::BootstrapError::Expired) => {
            return secured_mobile_text(StatusCode::UNAUTHORIZED, "bootstrap unavailable");
        }
    };

    let location = format!(
        "/mobile#request_proof={}&stream_ticket={}",
        session.request_proof, session.stream_ticket
    );
    let cookie = mobile::mobile_session_cookie(&session.session_cookie);
    let mut response = (StatusCode::SEE_OTHER, "").into_response();
    response.headers_mut().insert(
        header::LOCATION,
        HeaderValue::from_str(&location).expect("generated mobile fragment is a valid header"),
    );
    response.headers_mut().insert(
        header::SET_COOKIE,
        HeaderValue::from_str(&cookie).expect("generated mobile cookie is a valid header"),
    );
    secure_mobile_response(&mut response);
    response
}

async fn exchange_mobile_session(State(state): State<RuntimeApiState>, req: Request) -> Response {
    let Some(mobile_state) = state.mobile.as_ref() else {
        return mobile_not_found();
    };
    let Some(expected) = state.runtime_token.as_deref() else {
        return mobile_not_found();
    };
    if !auth::request_has_header_runtime_token(&req, expected) {
        return mobile_unauthorized();
    }
    mobile_session_response(mobile_state.issue_session())
}

View on GitHub (pinned to 433685b202)