Skip to content

[BUG] Password-protected deployment auth tokens can be forged #4759

@3em0

Description

@3em0

Describe the bug

Password-protected chat and form deployments use a base64-encoded authentication token that is not signed or bound to a server-side secret. The token format is:

deploymentId:type:timestamp:truncatedPasswordHash

The password hash is sha256(encryptedPassword).substring(0, 8), which gives only 32 bits of search space. validateAuthToken() accepts any token whose deployment ID matches, whose timestamp is within 24 hours, and whose 8-character password hash matches the current encrypted password value. Because the token is not authenticated with an HMAC/signature, a token can be created outside the server once the 32-bit hash value is guessed.

Affected code:

  • apps/sim/lib/core/security/deployment.ts
    • hashPassword() truncates SHA-256 to 8 hex characters.
    • encryptAuthToken() returns plain base64 of the token fields.
    • validateAuthToken() validates field equality but does not verify a server-side signature.
  • apps/sim/app/api/chat/utils.ts
    • validateChatAuth() trusts chat_auth_<deploymentId> when validateAuthToken() returns true.
  • apps/sim/app/api/form/utils.ts
    • validateFormAuth() trusts form_auth_<deploymentId> when validateAuthToken() returns true.
  • apps/sim/app/api/chat/[identifier]/route.ts and apps/sim/app/api/form/[identifier]/route.ts
    • GET handlers return full deployment configuration when the forged cookie validates.

This was verified on commit 7b572f1f61a8bbcee31fd7389097814a71f8f094 and the same vulnerable implementation is still present in fetched origin/main at e532e0a6da6fd22eee98310ba44e4fe50dec174a.

To Reproduce

Use only a local/synthetic deployment ID and encrypted password value. Do not run this against production systems.

  1. Inspect apps/sim/lib/core/security/deployment.ts.
  2. Compute the same password hash used by the application:
const { createHash } = require('crypto')
const encryptedPassword = 'synthetic-encrypted-password-ciphertext'
const pwHash = createHash('sha256').update(encryptedPassword).digest('hex').substring(0, 8)
  1. Construct a token outside the server:
const deploymentId = 'dep_safe_local_test'
const token = Buffer.from(`${deploymentId}:password:${Date.now()}:${pwHash}`).toString('base64')
  1. Pass the token to the same validation logic:
validateAuthToken(token, deploymentId, encryptedPassword) === true
  1. A wrong hash is rejected and an expired timestamp is rejected, confirming that the acceptance condition is exactly the forgeable 8-character hash plus a fresh timestamp.

Local verification result:

hash_bits=32
candidate_space=4294967296
forged_fresh_valid=true
wrong_hash_valid=false
expired_valid=false

Expected behavior

Deployment authentication cookies should be unforgeable by clients. A token should only validate if it was issued by the server and protected with a server-side secret, such as an HMAC-signed payload, authenticated encrypted token, signed JWT with strict claims, or an opaque server-side session ID.

The password hash should not be used as a bearer capability. If a stateless token is required, validation should verify a cryptographic signature using constant-time comparison and should bind the token to the deployment ID, auth type, expiration, and any relevant session/version state.

Screenshots

Not applicable. The issue is in token construction and validation logic.

Additional context

Security impact:

  • Unauthorized access to password-protected chat/form deployments is possible if an attacker knows the deployment identifier and can find the 32-bit truncated password hash.
  • The public deployment identifier is exposed through deployment URLs.
  • A valid forged cookie can make protected GET routes return full deployment configuration and can allow POST flows to proceed as authenticated.
  • Since the timestamp is client-controlled and only checked for recency, an attacker who finds the hash can mint fresh tokens until the password/encrypted password value changes.

Recommended remediation:

  • Replace plain base64 tokens with HMAC-signed tokens or opaque server-side session IDs.
  • Remove the truncated password hash from client-controlled token material.
  • Add rate limiting and monitoring for failed deployment-auth attempts.
  • Consider rotating deployment auth/session material after deploying a fix.

Disclosure note:

The repository contains .github/SECURITY.md, which asks reporters to email security@sim.ai and not disclose vulnerabilities publicly. This file follows the repository's bug-report template for private maintainer handling rather than public issue publication.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    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