Skip to content

Consider unsetting PIMONITOR_API_KEY from the process environment after config.Load #121

Description

@LarsLaskowski

Summary

Follow-up to #104 (and PR #120), which stopped PIMONITOR_API_KEY from being copied into the environment of child processes (apt, vcgencmd) by building an explicit, minimal cmd.Env instead of inheriting the full parent environment.

A stronger, but more invasive, follow-up was called out as explicitly out of scope there: config.Load could call os.Unsetenv("PIMONITOR_API_KEY") after reading the value, so the key disappears from the main pimonitor process's own environment (/proc/self/environ) entirely, not just from subprocess environments.

Why this is separate from #104

This is a bigger behavioural change than the subprocess fix:

  • It affects anything else in the process that might read PIMONITOR_API_KEY later (unlikely today, but a behavioural change nonetheless).
  • os.Unsetenv does not necessarily shrink or scrub the original environ block on all platforms/libc implementations — on Linux/glibc it typically does rewrite the block in place, but this should be verified rather than assumed, and the exact guarantee should be documented rather than implied.
  • It's a design decision worth reviewing on its own rather than bundling into a subprocess-environment hardening PR.

Suggested approach

  • In internal/config (wherever PIMONITOR_API_KEY is currently read via os.Getenv/os.LookupEnv), call os.Unsetenv("PIMONITOR_API_KEY") immediately after reading it into config, once it's no longer needed from the environment.
  • Confirm (and note in a comment / SECURITY.md) what guarantee this actually provides on Linux — i.e. whether /proc/self/environ is actually scrubbed afterward — rather than assuming it based on os.Unsetenv's general contract.
  • Add a test verifying that after config.Load runs (with PIMONITOR_API_KEY set via t.Setenv), os.LookupEnv("PIMONITOR_API_KEY") no longer finds it — being mindful that t.Setenv and manual unsetting inside the same test need to interact correctly (parallel tests and t.Setenv don't mix; note this in the test).
  • Update SECURITY.md's "Threat Model / Design Notes" section to mention this additional hardening step once implemented.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions