Audit what stayed behind after an uninstall (moraine) - #78
Open
heznpc wants to merge 1 commit into
Open
Conversation
Removing software does not remove what it registered, and the leftovers that
matter are the ones that keep acting on the machine after the app is gone.
Two records outlive the uninstall and neither is a file sweep:
pkgutil receipts every package ever installed, and whether its
payload still exists
trust domains root certificates in the admin/user stores, and how
broadly each is trusted
The verdict is the correlation. A trusted root whose installing package has no
payload left is a certificate still vouching for a vendor otherwise gone from
the machine, and neither source produces that alone.
First live run on this Mac found exactly that: INNORIX.CA, self-signed,
CA:TRUE, 2048-bit, valid to 2028-07-07, trusted unconditionally in the admin
domain -- installed 2026-05-01 by a Korean file-transfer plugin whose app,
LaunchAgent, and processes are all gone. macOS trust semantics are the trap
here: an empty usage-constraint array reads like "nothing configured" and
means the opposite, trust as root for every policy, so it is named explicitly
and pinned by a test.
A root with no owning receipt is reported "unattributed", never accused --
MDM profiles, enterprise Wi-Fi, and hand-imported roots legitimately have no
installer receipt. Large packages are file-sampled and any sampling is
reported. Nothing is written and nothing deleted; removing a trust root is an
admin act that stays a human decision.
Prior art was read rather than assumed. AppCleaner's location list is genuinely
vetted (BundlePaths.plist plus ~70 directories in its binary), but it is
target-driven -- you drop an app on it -- and its binary carries no SecTrust or
SecCertificate symbols, so trust-store contents are outside a file sweep.
mole reads pkgutil receipts too, in lib/core/pkg_receipts.sh, but only to
locate app bundles under /usr/local and /opt, never to judge whether a payload
survived.
Also corrects a claim in the README. Orca's workspace cleanup runs the same
rev-list --count HEAD --not --remotes check scree does, against the worktrees
it manages, so "no other tool asks" was false for the unpushed-work verdict.
The README now names the prior art and states the actual difference: scree
sweeps every agent worktree on the machine whatever created it, plus primary
checkouts stranded off main and registry entries whose directory vanished.
The judgment itself stays -- it is what cleanup's safety rests on, and the
canary absorption rested on scree already having it, neither of which depends
on nobody else having it too.
Exposed through the MCP surface as moraine_report, which the registration-time
read-only contract gates like the other three.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
소프트웨어를 지워도 그것이 등록한 것은 남습니다. 그중 문제가 되는 건 앱이 사라진 뒤에도 계속 머신에 작용하는 쪽입니다. 언인스톨보다 오래 사는 기록 두 개를 읽고 상관 판정을 냅니다.
pkgutil영수증핵심은 상관 판정입니다. 설치한 패키지의 payload가 사라진 채로 신뢰받는 루트 = 이미 머신에 없는 벤더를 여전히 보증하는 인증서. 어느 한 소스만으로는 못 내는 결론입니다.
이 맥에서의 첫 실행 결과
한국 파일 전송 플러그인이 2026-05-01에 깔면서 넣은 자체서명 루트입니다. 앱·LaunchAgent·프로세스는 전부 사라졌는데 인증서만 2028년까지 무조건 신뢰 상태로 남아 있었습니다.
macOS 신뢰 규약의 함정을 명시적으로 다룹니다: 사용 제약 배열이 비어 있으면 "설정 안 됨"처럼 읽히지만 실제로는 모든 정책에 대한 루트 신뢰입니다. 정반대로 읽히는 값이라 코드에 이름을 붙이고 테스트로 고정했습니다.
영수증이 없는 루트는
unattributed로 보고하고 혐의를 씌우지 않습니다 — MDM 프로파일·기업 와이파이·수동 임포트는 영수증이 없는 게 정상입니다. 큰 패키지는 파일 샘플링하고 샘플링 사실을 항상 보고합니다. 아무것도 쓰지 않고 아무것도 지우지 않습니다.선행 도구는 읽고 비교했습니다 (추측 아님)
lib/core/pkg_receipts.sh—/usr/local·/opt앱 탐색용, payload 생존 판정 없음SecTrust/SecCertificate심볼 0건dump-trust-settings0건AppCleaner의 위치 목록(
BundlePaths.plist+ 바이너리의 약 70개 디렉터리)은 실제로 잘 정비돼 있습니다. 다만 파일 스윕으로는 트러스트 스토어 내용에 닿지 못합니다.README 정정도 포함
Orca(
stablyai/orca)의 workspace cleanup이 scree와 같은 명령(rev-list --count HEAD --not --remotes)으로 미푸시 작업 판정을 합니다.src/main/ipc/workspace-cleanup-git-evidence.ts를 직접 받아 확인했습니다. 따라서 README의 "no other tool asks"는 워크트리 항목에 대해 거짓이었습니다.검증
pytest tests/ -q→ 473 passed (moraine 25 + MCP 4번째 도구 4 신규)compileall,release_smoke.py통과moraine_report로 노출, 등록 시점 읽기 전용 계약이 나머지 셋과 동일하게 게이트Swift UI 노출은 범위 밖이라 봉인 런타임 제외 목록에 조건과 함께 등록했습니다.