fix: validate CLI callback URLs to localhost-only
Reject non-localhost CLI callback URLs in the WebAuthn auth start endpoint to prevent token exfiltration to external servers.
This commit is contained in:
parent
24d9d75145
commit
7e0b910008
1 changed files with 24 additions and 5 deletions
|
|
@ -218,11 +218,17 @@ pub(crate) async fn auth_start(
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let cli_callback = match (query.cli_callback, query.state, query.token_name) {
|
let cli_callback = match (query.cli_callback, query.state, query.token_name) {
|
||||||
(Some(callback_url), Some(cli_state), Some(token_name)) => Some(CliCallbackInfo {
|
(Some(callback_url), Some(cli_state), Some(token_name)) => {
|
||||||
|
validate_cli_callback_url(&callback_url).map_err(|()| {
|
||||||
|
warn!(url = %callback_url, "rejected non-localhost CLI callback URL");
|
||||||
|
StatusCode::BAD_REQUEST
|
||||||
|
})?;
|
||||||
|
Some(CliCallbackInfo {
|
||||||
callback_url,
|
callback_url,
|
||||||
state: cli_state,
|
state: cli_state,
|
||||||
token_name,
|
token_name,
|
||||||
}),
|
})
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -466,6 +472,19 @@ pub(crate) async fn passkey_add_finish(
|
||||||
|
|
||||||
// --- Helpers ---
|
// --- Helpers ---
|
||||||
|
|
||||||
|
/// Reject CLI callback URLs that don't point to localhost.
|
||||||
|
/// This prevents an attacker from redirecting the bearer token to an external server.
|
||||||
|
fn validate_cli_callback_url(url_str: &str) -> Result<(), ()> {
|
||||||
|
let parsed = url::Url::parse(url_str).map_err(|_| ())?;
|
||||||
|
if parsed.scheme() != "http" {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
match parsed.host_str() {
|
||||||
|
Some("127.0.0.1" | "localhost" | "::1" | "[::1]") => Ok(()),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn create_session(state: &AppState, cookies: &Cookies, user_id: crate::domain::ids::UserId) {
|
async fn create_session(state: &AppState, cookies: &Cookies, user_id: crate::domain::ids::UserId) {
|
||||||
let session_token = generate_session_token();
|
let session_token = generate_session_token();
|
||||||
let session_token_hash = hash_token(&session_token);
|
let session_token_hash = hash_token(&session_token);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue