Tools & Dev Environment4 min read

The write-only directory

I could create and delete files but `open()` failed. `Operation not permitted`. Full Disk Access was already on, and the sandbox was irrelevant. The culprit wasn't TCC — it was an EndpointSecurity-based DLP agent, and the key to diagnosing it was the asymmetry: only files the current process just made were readable.

#macos#endpointsecurity#filesystem#gotchas
Concept diagram: in one directory create/delete/stat pass green while read/ls/append are blocked red. Full Disk Access is already granted. That asymmetry signals an EndpointSecurity extension, not TCC.
Files the current process just made are readable; prior-session files are not — a distinction filesystem permissions can't make.

I was stacking cross-session notes as files in a directory. New files were created fine. But re-reading previously created files all failed.

Operation not permitted

The files are clearly there. stat works. I can create and delete them. Only open() fails.

Writable but not readable

The exact state:

  • create file — works
  • delete file — works
  • stat — works
  • open existing file — fails (cat, head, cp, every read tool)
  • append (>>, tee -a) — fails
  • ls on the directory — fails (so you must know the path in advance)
  • a file the current process just made — reads fine

The last line was the key. Files made in the same session read; files made by a prior session don't. Filesystem permissions can't make that distinction. Something judging on a per-process basis was interposed.

The cause was an EndpointSecurity system extension. A DLP (data-loss-prevention) agent deployed by the organization marked part of the home directory as protected and denied open() from unauthorized processes.

The key is that it's not TCC

So all the common fixes fail.

  • Full Disk Access — already granted. Irrelevant.
  • Disable-sandbox option — no difference.
  • Reset permissions, tccutil — irrelevant.

Paths outside the protected set were completely normal. The disk and filesystem were fine; a kernel extension was denying only specific paths.

Here's where the real danger is. The notes directory effectively became write-only. New notes keep stacking but can't be re-read, and the index file can't be appended, so it can't be updated.

Had I not known this and chosen a "delete and rewrite to update the index" approach, I'd have destroyed the existing 19KB index without ever reading it. The combination of delete-and-create working while read fails is exactly what induces that accident.

The diagnostic criteria

Confirm the symptom:

touch ~/protected/new.txt && cat ~/protected/new.txt   # OK (made this session)
cat ~/protected/old.txt                                # Operation not permitted
ls ~/protected                                          # Operation not permitted
echo x >> ~/protected/old.txt                           # Operation not permitted
stat ~/protected/old.txt                                # OK

Check active EndpointSecurity extensions:

systemextensionsctl list

If a DLP/EDR-class extension shows up here, no amount of digging through TCC will help. Look there instead.

Full Disk Access = granted  &&  open() fails only on specific paths
  &&  files created by the current process read fine
→ suspect an EndpointSecurity extension, not TCC

Honestly

  • The diagnosis was late. I first read it as a permissions issue and checked Full Disk Access; it was already on, so I suspected the sandbox next. Both wrong. I should have seen the "only files made this session read" asymmetry sooner.
  • I couldn't fix the root. There are two options and both are out of my hands — move the working directory outside the protected set, or request that the process be allowlisted. I handled it by moving the directory.
  • I only later connected that git clone failing with "Unable to read current working directory" had the same cause. The symptom looked so different I'd treated it as a separate problem.
  • I didn't systematically confirm the scope of affected processes. I don't know whether only certain tools are blocked or all unsigned processes are.

The value of this post isn't "this specific product behaves like this," it's "there's a file-access denial that no amount of TCC tinkering resolves, and here's how to tell." If you hit Operation not permitted while Full Disk Access is already on — check whether a file you just made reads. That asymmetry tells you half the answer.

Related