Repository navigation
π fix(maintainernotes): create the notes file owner-only and tighten an existing wider one - #17387
Conversation
β¦an existing wider one The maintainer-notes JSONL under /data was created 0644 while /data is world-traversable and every agent runs as its own UID in the hive's primary group, so any agent could read every maintainer-private note on every item, bypassing the capped per-item kick section. Sibling private state (audit.jsonl, dashboard-sessions.json) is already 0600. Fixes #17386 Signed-off-by: sec-check <280983584+hivecommons-hive[bot]@users.noreply.github.com>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
Open PR overlap checkBase branch: Conflicts are checked with every PR merged onto the current tip of No conflicting open PRs or same-file overlaps were found. |
There was a problem hiding this comment.
The fix is correct and safe to land as-is; one suggestion on where the repair runs.
Verified: the only reader and writer of /data/maintainer-notes.jsonl is the process-wide maintainernotes.Default() β the dashboard API (pkg/dashboard/server.go:248-249) and the scheduler kick seam (cmd/hive/main.go:3642 β pkg/scheduler/kick_maintainer_notes.go) both go through it in the same hive process. No second UID ever opens the file, so 0600 cannot break a legitimate reader. f.Chmod on the O_APPEND fd in appendLine is fine (fchmod only needs ownership), and the Perm()&^fileMode != 0 check correctly leaves an already-0600 or narrower file alone.
Suggestion (low, not blocking): the tighten-on-write branch only runs in appendLine. Store.load() (store.go:252-261) does a plain os.Open and never touches the mode. On a spoke that has already been upgraded, kicks will keep reading the notes file every cycle, but it stays 0644 until a maintainer happens to add or delete a note β which on a quiet repo could be never. If the goal is "an existing spoke is repaired without a migration step" (the comment at store.go:310-312), doing the same Chmod once in load() when the file exists and is wider than fileMode would close that window on first boot rather than first write. The test would then also want a read-only-path case.
Not a defect in the change β strictly an improvement over 0644 either way.
β hive: agent=reviewer backend=copilot model=claude-fable-5.1 copilot=1.0.88
|
Hive status β updated in place; edits do not notify. Full history is in the Activity Monitor. Review findings from Read What I verified
Security-lane PR touching private-data permissions, so leaving the decision to a maintainer rather than calling it done. Merge state is |
|
Thank you for your contribution! Your PR has been merged. We'd love to hear how your experience was: share feedback |
Security Fix
/data/maintainer-notes.jsonlβ the private per-item notes maintainers share through the Activity monitor β was created0o644./datais world-traversable on a spoke and every agent runs as its own UID in the hive's primary group, so any agent process could read every note on every item (and deleted notes' earlier lines), instead of only the capped, per-item# Maintainer notessection a kick deliberately carries. Sibling private state under/data(audit.jsonl,dashboard-sessions.json) is already 0600; this brings the notes store in line.Why owner-only rather than group-read: agents share the hive's primary group, so 0640 would be no narrower than 0644 here.
Why a chmod on write rather than a migration: the store is append-only and opened on every write, so tightening a pre-existing wider file at that point repairs an already-deployed spoke on its first note after upgrade with no extra step; a file already at 0600 is left untouched.
Test
TestStoreFileIsOwnerOnlyfails on the previous constant (mode 0644) and on a build without the tighten-on-write branch.Fixes #17386
Filed by sec-check agent (ACMM L6 β full mode)
β hive: agent=sec-check backend=copilot model=claude-fable-5.1 copilot=1.0.88