Self Checks
Aitoearn version
Commit d3aa8be and earlier versions
Please select your platform
Mac
Steps to reproduce
AiToEarn Uses Public Default Authentication Secrets
Package
AiToEarn
Affected versions
Commit d3aa8bea5b146a8675607cf0144d891aad3e9683 and earlier versions
containing the affected code.
Patched versions
Unknown.
Description
Summary
AiToEarn contains public default values for authentication secrets. The
Electron server uses a static fallback for AUTH_SECRET to sign and verify
JWTs. The JWT payload contains isManager, and ManagerGuard grants manager
access when this claim is true.
The backend configuration also contains a static internalToken. The shared
authentication guard accepts this value directly as a Bearer token without
JWT verification or user lookup. Internal controllers protected by
@Internal() therefore rely on this publicly known value as their only
authentication factor.
Details
| Component |
File |
Issue |
| Electron server |
project/aitoearn-electron/server/src/auth/auth.module.ts |
Static fallback for AUTH_SECRET |
| Electron server |
project/aitoearn-electron/server/src/auth/manager.guard.ts |
Trusts isManager after JWT verification |
| Backend services |
project/aitoearn-backend/apps/aitoearn-server/config/config.yaml |
Static auth.secret and auth.internalToken defaults |
| Shared backend auth |
project/aitoearn-backend/libs/aitoearn-auth/src/aitoearn-auth.guard.ts |
Accepts internalToken directly |
Vulnerable Code
project/aitoearn-electron/server/src/auth/auth.module.ts:
JwtModule.register({
global: true,
secret: process.env.AUTH_SECRET || "<public static default redacted>",
signOptions: { expiresIn: '30d' },
})
The application places the manager flag inside the JWT:
const payload: TokenInfo = {
phone: tokenInfo.phone,
id: tokenInfo.id,
name: tokenInfo.name,
isManager: tokenInfo.isManager,
};
return this.jwtService.sign(payload);
ManagerGuard then accepts the authorization decision from the token:
const payload = await this.jwtService.verifyAsync(token, {
secret: process.env.AUTH_SECRET,
});
if (!payload.isManager) {
throw new UnauthorizedException();
}
The backend configuration also publishes static authentication values:
auth:
secret: <public static default redacted>
internalToken: <public static default redacted>
The shared guard accepts the internal token without establishing a user:
if (token === this.options.internalToken) {
return true;
}
PoC
Run only against a local test deployment.
JWT manager authorization
- Leave
AUTH_SECRET unset in the Electron server.
- Create a JWT with the public fallback key and a payload containing
isManager: true.
- Send the token as
Authorization: Bearer <token> to a route protected by
@Manager(), such as the manager creation route.
- Repeat the test with a unique random
AUTH_SECRET.
Example token-generation pseudocode:
const token = jwt.sign(
{ id: '<test-id>', isManager: true },
'<public static default redacted>',
{ expiresIn: '30d' },
);
Expected secure result: the forged token is rejected. The affected result is
that the request passes ManagerGuard and reaches the manager-only handler.
Internal bearer token
- Start the backend with the checked-in
internalToken value unchanged.
- Send that value as a Bearer token to an endpoint protected by
@Internal().
- For example, test the AI draft-generation internal endpoints using a body
that satisfies the endpoint DTO.
- Repeat with a newly generated internal token.
Expected secure result: an external request without an explicitly authorized
service credential is rejected. The affected result is that the static token
passes the guard without JWT verification, API-key resolution, or user lookup.
Attack Scenario
- An attacker reads the public repository and obtains the default values.
- The deployment does not override the corresponding environment/configuration
values.
- The attacker signs a JWT with
isManager: true, or sends the default
internalToken as a Bearer token.
- The server accepts the token as an authenticated manager or internal caller.
Impact
The Electron JWT fallback may allow unauthorized access to manager-only
handlers, including manager administration operations. The backend
internalToken may allow unauthorized access to internal service endpoints,
including operations that accept a caller-supplied userId.
The backend auth.secret path additionally uses the token id to resolve an
open user record. Its exact impact should be verified against the deployed
token-issuing path, but the checked-in value is not suitable as a production
JWT secret.
Recommended Fix
- Remove all static authentication fallbacks from source-controlled
configuration.
- Fail closed when
AUTH_SECRET, auth.secret, or internalToken is absent
or unchanged from a development value.
- Generate instance-specific cryptographically random secrets during secure
deployment and store them outside the repository.
- Replace the exposed values and invalidate tokens issued with them.
- Do not use a bearer string as an implicit internal identity; authenticate
service callers with scoped, rotatable credentials and enforce service-side
authorization.
- Add regression tests proving that default or missing secrets cannot start a
production deployment and that forged manager/internal requests are
rejected.
References
✔️ Expected Behavior
...
❌ Actual Behavior
...
Self Checks
Aitoearn version
Commit d3aa8be and earlier versions
Please select your platform
Mac
Steps to reproduce
AiToEarn Uses Public Default Authentication Secrets
Package
AiToEarn
Affected versions
Commit
d3aa8bea5b146a8675607cf0144d891aad3e9683and earlier versionscontaining the affected code.
Patched versions
Unknown.
Description
Summary
AiToEarn contains public default values for authentication secrets. The
Electron server uses a static fallback for
AUTH_SECRETto sign and verifyJWTs. The JWT payload contains
isManager, andManagerGuardgrants manageraccess when this claim is true.
The backend configuration also contains a static
internalToken. The sharedauthentication guard accepts this value directly as a Bearer token without
JWT verification or user lookup. Internal controllers protected by
@Internal()therefore rely on this publicly known value as their onlyauthentication factor.
Details
project/aitoearn-electron/server/src/auth/auth.module.tsAUTH_SECRETproject/aitoearn-electron/server/src/auth/manager.guard.tsisManagerafter JWT verificationproject/aitoearn-backend/apps/aitoearn-server/config/config.yamlauth.secretandauth.internalTokendefaultsproject/aitoearn-backend/libs/aitoearn-auth/src/aitoearn-auth.guard.tsinternalTokendirectlyVulnerable Code
project/aitoearn-electron/server/src/auth/auth.module.ts:The application places the manager flag inside the JWT:
ManagerGuardthen accepts the authorization decision from the token:The backend configuration also publishes static authentication values:
The shared guard accepts the internal token without establishing a user:
PoC
Run only against a local test deployment.
JWT manager authorization
AUTH_SECRETunset in the Electron server.isManager: true.Authorization: Bearer <token>to a route protected by@Manager(), such as the manager creation route.AUTH_SECRET.Example token-generation pseudocode:
Expected secure result: the forged token is rejected. The affected result is
that the request passes
ManagerGuardand reaches the manager-only handler.Internal bearer token
internalTokenvalue unchanged.@Internal().that satisfies the endpoint DTO.
Expected secure result: an external request without an explicitly authorized
service credential is rejected. The affected result is that the static token
passes the guard without JWT verification, API-key resolution, or user lookup.
Attack Scenario
values.
isManager: true, or sends the defaultinternalTokenas a Bearer token.Impact
The Electron JWT fallback may allow unauthorized access to manager-only
handlers, including manager administration operations. The backend
internalTokenmay allow unauthorized access to internal service endpoints,including operations that accept a caller-supplied
userId.The backend
auth.secretpath additionally uses the tokenidto resolve anopen user record. Its exact impact should be verified against the deployed
token-issuing path, but the checked-in value is not suitable as a production
JWT secret.
Recommended Fix
configuration.
AUTH_SECRET,auth.secret, orinternalTokenis absentor unchanged from a development value.
deployment and store them outside the repository.
service callers with scoped, rotatable credentials and enforce service-side
authorization.
production deployment and that forged manager/internal requests are
rejected.
References
✔️ Expected Behavior
...
❌ Actual Behavior
...