T09 · Insecure Skill Coding Practices
Warning
- Location
- references/circle-smart-account.md:55
- Finding
- Passkey Credential Objects Persisted in Browser localStorage## Vulnerability Details **File Location**: `references/circle-smart-account.md:55` and `references/circle-smart-account.md:67` **Vulnerability Type**: Sensitive authentication data stored in script-accessible browser storage **Risk Level**: Medium ### Vulnerable Code ```typescript const credential = await toWebAuthnCredential({ transport: passkeyTransport, mode: WebAuthnMode.Register, username: 'alice', }) // Persist credential so the user stays logged in across reloads localStorage.setItem('credential', JSON.stringify(credential)) ``` The login flow repeats the same insecure persistence pattern: ```typescript const credential = await toWebAuthnCredential({ transport: passkeyTransport, mode: WebAuthnMode.Login, }) localStorage.setItem('credential', JSON.stringify(credential)) ``` ### Technical Analysis The examples serialize a `P256Credential` object and place it in `localStorage`. Data in `localStorage` is available to every JavaScript context running under the same origin. It does not receive the confidentiality protections provided by an `HttpOnly` session cookie. Consequently, an attacker who obtains same-origin script execution through cross-site scripting, a compromised frontend dependency, malicious analytics code, or another injected script can read and export the serialized credential object. The exact ability to authenticate using the extracted object depends on the SDK representation and authenticator requirements; WebAuthn private key material should ordinarily remain inside the authenticator. Nevertheless, exposing credential identifiers and related authentication state increases the impact of frontend compromise and may facilitate session abuse, correlation, credential-targeting attacks, or replay attempts where the surrounding implementation improperly treats the serialized object as sufficient authentication state. The parent Skill recognizes this risk in `SKILL.md` by stating that `localStorage` is for a quick example onl ...[truncated 1686 chars]
- Remediation
- ## Remediation Suggestions - Remove all examples that serialize sensitive credential objects into `localStorage`. - Keep WebAuthn private key operations within the platform authenticator and persist only the minimum non-secret credential identifier or account metadata required by the application. - Use a server-managed session represented by a cookie configured with `HttpOnly`, `Secure`, and an appropriate `SameSite` policy. - Require a fresh WebAuthn assertion before sensitive wallet operations instead of treating restored browser data as proof of authentication. - Apply a restrictive Content Security Policy and Trusted Types where supported to reduce XSS exposure. - Minimize third-party scripts and audit frontend dependencies that execute in the wallet origin. - Clear obsolete authentication state on logout, account recovery, credential revocation, and session expiry. - Make the secure implementation the primary reference example rather than relying solely on a warning in `SKILL.md`.
