Builder & Transaction Security Testing
Ensures that builder-based transaction flows never bypass the wallet's approval pipeline and that storage accounts cannot be created implicitly through generic publish operations.
Overview
The builder & transaction security suite focuses on two critical invariants for non-custodial safety:
- Storage creation interception — a dApp must not be able to silently create long-lived storage accounts via a generic
keeta_builder_publishcall. - Approval enforcement for value movement — any builder operation that moves tokens must always be surfaced as a
PendingDappRequestthat the user explicitly approves.
These checks reinforce the zero-custody design: the user signs everything, and no background logic can move funds or create storage on the user's behalf without an approval surface.
Running the Tests
# From keythings-monorepo root
# Run as part of the comprehensive security suite:
bun run security:comprehensive
# Or run this suite directly:
bun tests/security/suites/builder-transaction-security-tests.tsKey Invariants & Code Excerpts
1. Storage Account Creation Interception
The first test ensures that attempts to create storage accounts via keeta_builder_publish are intercepted and rejected with a clear error instead of being executed as a generic publish:
async function runStorageCreationInterceptionTest(handler: Handler): Promise<void> {
const operations = [
{
type: 'setInfo',
info: { name: 'Storage Account', description: 'Test storage', metadata: '{}' },
account: { publicKeyString: 'keeta_storage_account_placeholder' },
},
] as Array<Record<string, unknown>>
const response = await sendRpc(handler, 'keeta_builder_publish', [operations])
const asError = response instanceof Error ? response : null
if (asError && /Storage account creation via builder must be requested separately/i.test(asError.message)) {
recordFinding({
area: 'Builder',
name: 'Storage creation intercepted when embedded in builder',
severity: 'low',
})
return
}
recordFinding({
area: 'Builder',
name: 'Storage account creation via builder was not intercepted',
severity: 'high',
})
}Vulnerability detected: If the wallet does not reject embedded storage creation, a dApp could smuggle storage operations into otherwise normal-looking builder flows. This can undermine separation between ephemeral transactions and long-lived storage accounts.
Severity: Missing interception is reported as high severity. Successful interception is recorded as low (affirmative evidence that the guardrail is active).
2. Builder Approval Enforcement
The second test verifies that any builder operation that moves value (for example a send) is converted into a pending approval request and cannot execute silently:
async function runBuilderApprovalEnforcementTest(handler: Handler): Promise<void> {
const before = await handler.listPendingDappRequests()
const operations = [
{
type: 'send',
to: { publicKeyString: 'keeta_recipient' },
amount: '1',
token: { publicKeyString: 'keeta_token' },
},
] as Array<Record<string, unknown>>
await sendRpc(handler, 'keeta_builder_publish', [operations])
const after = await handler.listPendingDappRequests()
const newRequests = after.slice(before.length)
const hasBuilderPublish = newRequests.some((req) => req.requestType === 'builderPublish')
if (!hasBuilderPublish) {
recordFinding({
area: 'Builder',
name: 'Builder send operation did not create a pending approval request',
severity: 'high',
})
return
}
recordFinding({
area: 'Builder',
name: 'Builder send operations require approval',
severity: 'low',
})
}Vulnerabilities detected:
- Sending tokens without creating a
PendingDappRequest(silent transfers with no approval surface). - Builder flows that bypass standard approval UX, making it harder for users to understand or revoke permissions.
Severity: Any missing approval is high severity, since it directly impacts the user's ability to consent to value movement.
Vulnerability Classes & Severity
| Check | Vulnerability | Severity |
|---|---|---|
| Storage creation interception | Implicit storage account creation via generic builder publish | High |
| Builder approval enforcement | Value-moving operations without explicit user approval | High |
Research & References
Builder & transaction security is heavily influenced by the broader ecosystem's experience with token approvals and delegated spending:
- Token Approvals & Spending Caps: ConsenSys and MetaMask document the risks of unlimited token approvals and the importance of spending caps and revocation in their guidance on permissions and approvals.
- Non-Custodial Design: Our zero-custody architecture ensures that the backend never holds private keys. By enforcing builder approvals, we extend this principle to transaction construction: the user must always approve movements created by builders.
This suite, together with the Advanced Security andData Exfiltration suites, provides strong assurance that builder-based flows cannot be abused to take custody or move funds without explicit, revocable consent.