Skip to content

[SECURITY] HMAC secret stored in plaintext on disk #29

@kiosvantra

Description

@kiosvantra

Security Finding: HMAC Secret Stored in Plaintext

Severity: High
Component: whisperopencode-push (bundled plugin)

Description

The relay authentication secret (channel_secret) is stored in plaintext in the local state file at:

~/.local/share/opencode/push/whisperopencode-push.json

The state file permissions are set to 0o600 (owner read/write only), which mitigates exposure on single-user systems. However, on shared systems, any local user with the same UID can read the secret.

Impact

If a local attacker gains read access to the state file, they can:

  • Impersonate the plugin to the relay server
  • Receive push notifications intended for the victim
  • Potentially pair new devices without the owner's consent

Evidence

State file structure (from state.js):

data.relay = {
    url: res.relay_url,
    channel: res.channel_id,
    secret: res.channel_secret,  // <-- plaintext secret
    server,
};

Written with fs.chmod(file, 0o600) which only restricts access on single-UID systems.

Recommendation

Consider encrypting the secret at rest using a user-level key derived from a password or machine-specific secret (e.g., keyed by OPENCODE_TEST_HOME or a local keychain). Alternatively, store only the hash of the secret for verification purposes and keep the plaintext secret in a OS-level credential store.

References

  • File: dist/src/state.js
  • Config path: dist/src/path.js (stateFile function)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions