Skip to content

Issue-boundary redaction: CommitmentLog skips WorkRedact, and an install cannot add its own deny patterns #2529

Open

Description

@drpaulobernardy

What happened

WorkRedact (from #1825) strips credential shapes, emails, phones, government-ID and card numbers and home paths before WorkSweep creates an issue. Two gaps remain at the same boundary:

  1. LIFEOS/TOOLS/CommitmentLog.ts builds the title and body from --beneficiary, --subject and --source-link and runs gh issue create directly (:81-117). It does not call redactIssuePayload. The --beneficiary field is a name by design, so even if it were redacted, no fixed pattern class would catch it. The same is true of the other gh issue create writers that do not import the redactor (SOCRATES/Router.ts:164, VIGIL/Tick.ts:45, KnowledgeDistill.ts:302, skills/X/Tools/bookmark-issue.ts:313); I did not check what they carry.
  2. The pattern set is fixed in code (WorkRedact.ts CLASSES). What counts as sensitive depends on the install: an internal record ID format, a customer or patient code, a project codename. The shipped classes cannot know them, and a user cannot add them without patching a shipped file.

Issue content is effectively permanent once created (#1825), so a miss is not recoverable by a later fix.

Read, not run.

Root cause

redactIssuePayload is called at one write site instead of being the one gate every issue/comment writer goes through, and it reads no install-level configuration.

Suggestion

  1. Add an optional LIFEOS/USER/CONFIG/issue-redaction.json, loaded by redactIssuePayload and merged after the built-in classes:
{
  "patterns": [
    { "name": "internal-id", "regex": "\\b[A-Z]{1,3}-\\d{3,6}\\b", "action": "refuse" },
    { "name": "codename",    "regex": "\\bproject-atlas\\b",     "action": "redact" }
  ]
}

redact replaces with [REDACTED:<name>] like the built-ins. refuse throws, so the writer fails loudly and nothing is filed. Failing is the safer default for identifiers where a mask is not enough (the mask may still reveal that a record exists), and it fits the "no silent fallback" rule the rest of the system follows. With no config file, behaviour is unchanged.
2. Call it from CommitmentLog.ts and the other issue writers (title and body, and comment bodies for any gh issue comment).
3. Add a lane next to issue-repo-provenance that fails when a file matching ISSUE_WRITE_RE does not import redactIssuePayload, so the next writer cannot skip it.

We carry a small local guard of this kind (a deny-pattern check run before any outbound issue or comment) and it has caught real cases that no generic class would. Happy to turn it into a PR against WorkRedact.ts if the config shape is acceptable.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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