ComposioHQ/composio · error · KeyringError
user must not contain NUL bytes
Error message
user must not contain NUL bytes
What it means
The macOS keyring store validates its inputs before shelling out to the `security` command. Because arguments are passed to a subprocess, embedded NUL bytes (`\0`) would truncate or corrupt the argv string, so the store rejects any `user` value containing NUL bytes with an Invalid KeyringError.
Source
Thrown at ts/packages/cli-keyring/src/stores/macos-security-subprocess.ts:74
}
throw new KeyringError({
kind: 'NotSupportedByStore',
operation: `macos keychain domain "${domain}"`,
});
}
function validateSpecifier(service: string, user: string): void {
// Empty service or user would become wildcards in Keychain Services
// — keyring-rs throws `Error::Invalid` here and we match that.
if (service.includes('\0')) {
throw new KeyringError({
kind: 'Invalid',
param: 'service',
reason: 'service must not contain NUL bytes',
});
}
if (user.includes('\0')) {
throw new KeyringError({
kind: 'Invalid',
param: 'user',
reason: 'user must not contain NUL bytes',
});
}
}
function classifyExitCode(result: SpawnResult, operation: string): KeyringError {
const code = result.code;
const stderr = bytesToUtf8(result.stderr).trim();
if (code === EXIT_ITEM_NOT_FOUND) {
return new KeyringError({ kind: 'NoEntry' });
}
if (code !== null && EXIT_NO_STORAGE_ACCESS.has(code)) {
return new KeyringError({
kind: 'NoStorageAccess',
cause: new Error(stderr || `security ${operation} failed with exit ${code}`),
});View on GitHub (pinned to 64b1b85502)
Solutions
- Inspect and sanitize the user string before calling the keyring API: strip or reject '\0'.
- Trace where the user value originates (env var, config file, IPC payload) and fix the encoding/truncation bug upstream.
- If NUL is legitimate in your data, it cannot be a keyring user name — hash or encode it first.
Example fix
// before
await store.setSecret(service, userWithNul, secret); // throws Invalid
// after
if (user.includes('\0')) throw new Error('invalid user');
await store.setSecret(service, user, secret); Defensive patterns
Strategy: validation
Validate before calling
function isValidKeyringUser(user: string): boolean {
return user.length > 0 && !user.includes('\0');
} Try / catch
try {
await store.setSecret(service, user, secret);
} catch (e) {
if (e instanceof KeyringError && e.kind === 'Invalid' && e.param === 'user') {
// sanitize and retry with a cleaned user value
}
} Prevention
- Validate user/service strings at the boundary where they enter your app, before reaching the keyring.
- Avoid passing Buffers or raw binary as keyring identifiers; stringify and sanitize first.
When it happens
Trigger: Calling setSecret, getSecret, or deleteCredential on the macOS-security store with a user string that contains a '\0' character (e.g. a Buffer read past its data, or malformed serialized credentials passed as the user parameter).
Common situations: Passing binary data or an unsafely-decoded buffer as the user/account name; truncated strings from IPC or JSON with literal \u0000 escapes; fuzzed input reaching the keyring layer.
Related errors
- PlatformFailure
- dlsym(${name}) failed
- CFStringCreateWithBytes returned NULL
- CFDataGetBytePtr returned NULL
- CFDictionaryCreateMutable returned NULL
AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28).
Data as JSON: /api/errors/62b80b8268af7e3c.
Report an issue: GitHub.