Skip to content

🔒 Local callback server accepts API key from any origin (no CSRF protection) #745

Description

@sulthonzh

Description

The local callback server started during API key authentication (start_callback_server in apikey_auth.rs) accepts POST requests from any origin. Combined with the Access-Control-Allow-Origin: * CORS header, any website the user visits could POST a malicious API key to localhost:5269-5278.

Context

  • File: cli/src/apikey_auth.rs (start_callback_server function)
  • Component: API key authentication callback server

Current Behavior

The callback server:

  1. Binds on ports 5269-5278 on localhost
  2. Responds with Access-Control-Allow-Origin: *
  3. Accepts any POST request containing a string starting with stkpk_api
  4. No CSRF token, no state parameter, no origin validation

A malicious website could:

<script>
fetch("http://localhost:5269/", {
  method: "POST",
  body: "stkpk_api_attacker_controlled_key_here",
  headers: { "Content-Type": "text/plain" }
});
</script>

If the user visits a malicious page while the callback server is running during auth, the attacker-controlled key gets saved to config.

Expected Behavior

Add a random state/token that must be included in the callback:

+ // Generate a random state token at server start
+ let state_token = uuid::Uuid::new_v4().to_string();

  // In POST handler:
- if let Some(api_key) = extract_api_key_from_post_body(&request) {
+ if let Some(api_key) = extract_api_key_from_post_body(&request) {
+     // Validate state token from query string or body
+     if !request.contains(&state_token) {
+         // reject - missing or invalid state
+         continue;
+     }
      let _ = tx.send(api_key.clone()).await;

The state token should be:

  1. Generated when the server starts
  2. Included in the browser redirect URL as a query parameter
  3. Validated on every POST callback

Also restrict CORS to only the expected origin:

- "Access-Control-Allow-Origin: *\r\n"
+ "Access-Control-Allow-Origin: https://stakpak.dev\r\n"

Steps to Reproduce

  1. Start stakpak auth login
  2. While the callback server is listening, visit a webpage containing the fetch snippet above
  3. The attacker-controlled key is accepted and saved

Impact

  • Severity: Medium — requires user to be actively authenticating AND visit a malicious page simultaneously
  • Affected users: All users during the API key auth flow
  • Risk: Attacker could redirect API calls through their proxy

Environment

  • All versions with the callback server auth flow

Positively — happy to submit a PR if this is welcome.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions