T09 · Insecure Skill Coding Practices
Error
- Location
- src/lib/auth.ts:5
- Finding
- Predictable JWT Fallback Secret Enables Session Forgery<![CDATA[ ## Vulnerability Details **File Location**: `src/lib/auth.ts:5-7`; duplicated in `src/app/api/auth/session/route.ts:6-8` **Vulnerability Type**: Predictable cryptographic secret and authentication bypass **Risk Level**: Critical ### Vulnerable Code ```ts const JWT_SECRET = new TextEncoder().encode( process.env.JWT_SECRET || 'openclawdy-secret-key-change-in-production' ) ``` The resulting secret is used to verify a bearer token and trust its `agentId` claim: ```ts const { payload } = await jwtVerify(token, JWT_SECRET) const agentId = payload.agentId as string const agent = await prisma.agent.findUnique({ where: { id: agentId }, }) ``` ### Technical Analysis When `JWT_SECRET` is absent, the application signs and verifies HS256 tokens with a predictable value published in the repository. HS256 uses the same secret for signing and verification, so anyone who knows this fallback can create an apparently valid token. The verifier accepts the token-provided `agentId` and loads the corresponding agent without requiring a wallet signature or validating that an address claim matches the database record. Consequently, knowledge of another agent's identifier is sufficient to forge a session for that agent in deployments using the fallback. The vulnerable fallback is independently declared in both the shared authentication library and session route, increasing the likelihood of an insecure deployment. ### Attack Path 1. The application is deployed without a valid `JWT_SECRET`. 2. An attacker obtains or guesses a target agent ID through logs, API responses, database leakage, or another application flaw. 3. The attacker creates an HS256 JWT containing the target `agentId`. 4. The attacker signs the token with `openclawdy-secret-key-change-in-production`. 5. The forged token is sent as `Authorization: Bearer <token>`. 6. `jwtVerify` accepts the token, and the application loads the victim's agent record. 7. The attacker invokes memory APIs under the vict ...[truncated 488 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Remove the fallback value and fail application startup when `JWT_SECRET` is unset. - Require a cryptographically random secret of at least 256 bits, stored in a deployment secret manager. - Rotate any JWT secret used by an environment that may have fallen back to the published value. - Invalidate all existing sessions after rotation. - Validate required claims, including `sub`, `iss`, `aud`, `iat`, and `exp`. - Bind the token subject to the authenticated wallet and confirm that any address claim matches the loaded database record. - Consider asymmetric signing so verification services do not possess the signing key. - Add deployment-time configuration validation and a regression test proving that startup fails without the secret. ]]>
