Home-Path Redaction in Published PR Content (security)
internal/safepathis the one owner of home-directory redaction, the path analogue ofinternal/safeurl.RedactTextrewrites the process's own home plus/home/<user>,/Users/<user>, andC:\Users\<user>to~, unconditionally and for every occurrence. Add new shapes there rather than scrubbing paths at a call site. Candidate resolution must stay free offilepath.IsAbs/VolumeNameand of any reliance onfilepath.Clean's separator normalisation: those answer for the build platform, and on WindowsIsAbsdiscards the POSIX-rootedHOMEthat Git Bash, MSYS2, and Cygwin set - silently disabling redaction instead of failing. Regression:TestUsableHomeCandidate_AcceptsBothPlatformSpellings,TestHomeCandidates_AreSeparatorSpellingIndependent.PRStep.buildPRContentis the single render boundary: it drafts throughdraftPRContentand returnsredactPRContent(content), andExecutepublishes exactly that. Every source that can reach a PR body - agent prose, extracted intent, findings, fix summaries, step errors, artifactpath, artifact captions, and captured output embedded from evidence files - is covered there, so a new rendering path cannot reintroduce the leak. Redaction runs after every length cap, which is only safe because the placeholder is never longer than the path it replaces.- The
artifacts[].pathdescription intestFindingsSchema(common.go) must not solicit absolute paths, and must not forbid them either. The renderer's allowlist is the worktree or the run's evidence directory and a path under neither is dropped, while the evidence directory defaults under the operator's home - so soliciting more just re-supplies what the boundary has to strip, and a blanket "never report a home directory path" clause makes an obedient agent drop its own evidence. Publication safety is thepr.goboundary's job; the schema only stops soliciting paths from elsewhere on the machine. Regressions:TestTestFindingsSchema_DoesNotSolicitAbsolutePaths,TestTestFindingsSchema_KeepsEvidenceDirectoryPathsReportable. - Two other public surfaces deliberately do NOT share this rendering and are not covered: agent-authored commit subjects (
commitAgentFixes->Commit.RenderFixMessage), which reach the remote through Push, and the opt-in evidence branch (test.evidence.store_in_repo), which copies artifact files verbatim. Keep theinternal/safepathpackage doc honest about that scope. - The PR body must contain exactly ONE live pipeline-attestation marker, the run's own.
require-no-mistakes(.github/actions/require-no-mistakes/verify.py) binds the FIRST marker in the RAW body to the PR head, so a foreign copy placed earlier fails a PR the pipeline did produce - and a code fence is no defense, because that scan is raw text. Step agents embed foreign markers routinely, by capturing a generated PR body as evidence. - Neutralize at the assembly choke point (
appendGeneratedSectionsToCleanBodyWithinLimitplus the two intent paths), never per render path.pipelineMDalone carries the real marker and is left intact;BuildPipelineSummaryForneutralizes its own step-detail blocks, which quote agent text. A first attempt put this inescapePipelineFoldMarkers- per-render-path - and shipped three live foreign markers to #831 anyway. Regressions:TestPRStep_ForeignAttestationsInEveryComponentDoNotShadowTheRealOne(all components at once), plus the per-component guards inpr_test.go. - Regressions:
internal/safepath/redact_test.go,internal/pipeline/steps/pr_homepath_test.go.