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.
- Inspect
apps/sim/lib/core/security/deployment.ts.
- 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)
- Construct a token outside the server:
const deploymentId = 'dep_safe_local_test'
const token = Buffer.from(`${deploymentId}:password:${Date.now()}:${pwHash}`).toString('base64')
- Pass the token to the same validation logic:
validateAuthToken(token, deploymentId, encryptedPassword) === true
- 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.
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:
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.tshashPassword()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.tsvalidateChatAuth()trustschat_auth_<deploymentId>whenvalidateAuthToken()returns true.apps/sim/app/api/form/utils.tsvalidateFormAuth()trustsform_auth_<deploymentId>whenvalidateAuthToken()returns true.apps/sim/app/api/chat/[identifier]/route.tsandapps/sim/app/api/form/[identifier]/route.tsThis was verified on commit
7b572f1f61a8bbcee31fd7389097814a71f8f094and the same vulnerable implementation is still present in fetchedorigin/mainate532e0a6da6fd22eee98310ba44e4fe50dec174a.To Reproduce
Use only a local/synthetic deployment ID and encrypted password value. Do not run this against production systems.
apps/sim/lib/core/security/deployment.ts.Local verification result:
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:
Recommended remediation:
Disclosure note:
The repository contains
.github/SECURITY.md, which asks reporters to emailsecurity@sim.aiand not disclose vulnerabilities publicly. This file follows the repository's bug-report template for private maintainer handling rather than public issue publication.