Reading width
Wide uses the full column for everything, text, diagrams, code, and exercises. Narrow keeps the standard reading width.
Text size
Scales the body text. Headings and code blocks keep their size.
In this section
Setting Up a macOS Forensics Environment: Host, Case Structure, Toolstack
Introduction
Building a Mac you can examine evidence on means deliberately weakening the controls that stop software running and stop processes reading files.
That is uncomfortable stated plainly, and it should be, because the configuration you end up with is close to the configuration an attacker wants on a victim's machine. The machine cannot tell the two intentions apart, and neither can anybody reading it afterwards.
So this section is about doing it narrowly. Which control is refusing you, why it refuses, and the smallest repair that clears one tool rather than opening the whole system.
Scenario
An analyst downloads an open-source parser, and it will not open. The message says the application is damaged. They try reinstalling it, then move it to another folder, then turn off the system's security assessment globally so the rest of the toolkit will run too. The tool now works and nobody records what was changed.
Three refusals, three subsystems
And they get confused for each otherThree different controls can refuse you and they look identical from a keyboard. One decides whether your tool may run at all, assessing software that arrived from outside. A second decides whether a running process may read the files you point it at, applied per application rather than per user. A third protects the system's own files from everybody, including the root account.
THREE REFUSALS AND WHERE EACH COMES FROM
the tool will not launch assessment of downloaded software
the tool runs but reads none the privacy layer, per application
a system path stays closed integrity protection, even for root
each has its own remedy and none of them is the same switch
Read the block as three refusals from three subsystems. One global switch appears to fix all of them, which is exactly why reaching for it is the wrong instinct: published guidance is direct that reinstalling, moving folders, changing execute bits or disabling security globally may change the symptom without explaining the cause.
Knowing which of the three is refusing you is the whole of this section, and it takes one command per case. Everything after this is diagnosis before repair, and a repair sized to what the diagnosis found. That order is not fussiness. Each of the three has a different blast radius, and the one most people reach for first is the one that changes the most.
The three also fail at different moments, which is a useful way to tell them apart before running anything. The first refuses at launch, so you never get a process. The second lets the process start and returns nothing useful when it reaches for a protected path, which reads as an empty result rather than as an error. The third refuses a specific path while everything else works normally. An examiner who notices which of those three shapes they are looking at has usually identified the subsystem before opening a terminal. The second shape is the dangerous one, because an empty result looks like a finding and an error does not. An examiner who reports that a path held nothing, when the truth is that their tool was never permitted to read it, has made a claim about the evidence out of a fact about their own configuration.
Damaged means something specific
And it does not mean damagedThe message in the scenario is not describing the file it names. Published description is precise about it: a browser-downloaded application that is unsigned reports that it is damaged and cannot be opened, and it is not damaged. That is the assessment refusing an unsigned, quarantined application, in wording that sends people looking for corruption that was never there.
So the correct reading of that message is a state rather than a fault, and it names two facts about the bundle rather than one about its contents.
WHAT THE MESSAGE SAYS, AND WHAT IT MEANS
on screen "ParserTool.app is damaged and can't be opened"
actually the bundle carries the download attribute
and it has no signature the assessment will trust
not anything at all about the integrity of the file
Read the block as a translation rather than a diagnosis. The file on disk is intact, its hash matches whatever the publisher advertised, and every byte of it is exactly what was downloaded.
Reading it correctly is what rules out the three wrong fixes before any of them is attempted. The wording is worth being angry about for a moment, because it costs real time across the profession. A message reporting damage sends people to re-download the file, verify a checksum, or look for corruption, and none of those touches either of the two facts actually responsible. The behavior is most visible on current hardware, where an unsigned application fetched through a browser produces exactly this message on first launch. Knowing that saves the twenty minutes almost everybody spends on it once.
It also explains why the fix circulating in release notes and forum answers is usually a single command clearing the attribute. That command works because it removes one of the two facts, and it is the right instinct at the wrong scale when applied across a whole directory rather than to the bundle that refused.
The auditor above holds the configuration the scenario's analyst ended up with. Several lines in it are reasonable and some are considerably wider than the job required. Work it before the practice card.
One line in it is the hardest to judge and worth flagging in advance. Granting full disk access to the terminal rather than to the individual parsers is defensible, because something has to hold that access for a tool to read protected paths, and it is also the broadest possible way to grant it. Deciding where you land on that is more useful than being told.
The failure is a combination
Which is why one fix missesWhy some downloaded tools launch and others do not, from the same folder, is a question with an exact answer. Published analysis makes the condition explicit: the block comes from a combination of two facts rather than from either alone. The application still carries the attribute marking it as downloaded, and it has no signature the assessment is willing to trust.
Four pairings, and only one of them blocks.
Read the grid by cell rather than by row, because the outcome is a property of the pairing and neither axis decides it alone.
The pairing that actually blocks
Downloaded, and unsignedWhy the other three cells matter as much
- Published description names this pairing as sufficient on its own, so neither property alone predicts the outcome.
- Remove the attribute and the assessment is never triggered, whatever the signature says.
- Keep the attribute and add a signature the system trusts, and the same program passes.
Three of the four cells let the program run, which is why an examiner reasoning from a single property will predict the wrong outcome most of the time.
Read the rows across rather than down, because they describe one mechanism under four conditions. An unsigned application not carrying the attribute may behave differently, since the attribute is what triggers the assessment in the first place, and a signed and notarized download may pass despite carrying it.
The practical consequence is that both facts have to be checked before deciding what to change. A repair aimed at the attribute on a tool whose real problem is the signature will appear to work once and fail on the next download, which is how a workstation accumulates changes nobody can account for. Six months of that produces a machine whose behavior nobody can predict and whose results nobody can reproduce. The accumulation is the real risk rather than any single change, because each one was reasonable at the moment it was made and none of them was written down.
There is a fourth condition in the table worth reading rather than skipping: neither fact present. A tool that arrived without the attribute and carries no signature is not blocked, because there is nothing to trigger an assessment in the first place. That combination is unremarkable on a workstation and it is the same combination the attack in a later section depends on, which is the first hint that the mechanism cuts both ways. Nothing distinguishes a tool you fetched deliberately from anything else that arrived by the same route, which is a property of the mechanism rather than an oversight in it. Treat the four rows as a decision table you run against any tool that will not start: establish the attribute, establish the signature, and the row you are in names the change to make.
The narrow repair
One tool, not the systemThe repair should be the size of the problem, and the problem is one bundle. Published guidance describes the smallest local repair for a tool you understand and trust: inspect the attribute, verify the signing state, apply a local ad-hoc signature to that one bundle, remove the attribute from that one application, and verify the result.
# Diagnose: is it carrying the download attribute, and is it signed?
% xattr -l /Applications/ParserTool.app
% codesign -dv --verbose=2 /Applications/ParserTool.app
# Repair one bundle only, then confirm
% codesign --force --deep --sign - /Applications/ParserTool.app
% xattr -dr com.apple.quarantine /Applications/ParserTool.app
% spctl --assess --verbose /Applications/ParserTool.app
Read the commands as a diagnosis followed by a narrow repair. Run the first pair before touching anything, because published guidance is explicit that the point is not to turn off the system's security globally but to fix one known local tool while keeping the safety boundary clear.
The last command is the one people skip, and it is the one that matters afterwards. Verifying turns a change you made into a change you can describe, and describing it is the whole difference between a configured workstation and a mysterious one that somebody else inherits.
A note on the ad-hoc signature, since the phrase does more than it appears to. Signing locally does not vouch for the tool's origin and makes no claim about who wrote it; it gives the bundle a signature this machine will accept so that the assessment has something to evaluate. That is why it pairs with clearing the attribute rather than replacing it, and why it is an appropriate step only for a tool whose provenance you already established by other means. Reading the source, checking a published hash, or obtaining it from a party you already trust are all such means; the signature records a decision you made rather than substituting for it.
It is also worth noting what the repair does not do, since somebody will eventually ask whether it has compromised the machine. Signing one bundle and clearing one attribute changes the standing of one application and leaves the assessment fully in force for everything else that arrives afterwards, which is precisely the property the global switch destroys. The distinction between a narrow change and a broad one is the entire argument of this section, and it is the one a reviewer will test.
Some archives strip the attribute
Which is a trap in both directionsHow a tool arrives decides whether the attribute is there to be dealt with at all. Published research found that certain third-party archiving and virtualization utilities, and some of the platform's own command-line tools, do not enforce the attribute, so files extracted or fetched through them may never inherit it.
THE SAME TOOL, THREE ARRIVAL ROUTES
downloaded in a browser attribute applied, assessment runs
extracted by some archivers attribute may not be inherited
fetched by a command-line
transfer utility attribute not applied
the middle and bottom routes skip the check entirely
Read the block as three arrival routes rather than three tools. Only the first behaves the way people expect, and published research frames the consequence as a weakness in the assessment mechanism, since software can reach a machine without ever being evaluated.
For your own workstation that looks like convenience and saves a step. For an investigation it is a finding, because a binary on a subject machine carrying no such attribute did not necessarily arrive by any route a user would recognize as normal, and that absence is a thing to notice rather than to pass over.
The same reasoning runs forward into how you handle your own toolkit. If you fetch parsers with a command-line utility because it is faster, you have chosen a route that leaves no record of where they came from, on the machine whose configuration you will later have to describe. Downloading through a browser and clearing the attribute deliberately costs one extra command and leaves the arrival visible, which is the better trade on a machine that produces evidence. The general rule is that convenience which removes a record is worth less on an analysis machine than it is anywhere else, because the record is part of what the machine is for. The same logic explains why extracting a toolkit from an archive deserves a moment's thought rather than a double-click, given that some archivers drop the attribute without announcing it. Knowing which of your own utilities does that is a fact about your workstation worth establishing once.
Your workstation is the ideal victim
And this is the uncomfortable partThe previous two sections have a consequence worth sitting with rather than skipping past. Published analysis describes the pattern directly: where a program is fetched by a signed system transfer utility it does not receive the attribute, and where the terminal application has been granted full disk access the assessment will not block the process on execution or even warn the user.
Two intentions, one configuration, and the machine cannot tell them apart.
Read the two top boxes as the same list written twice. Nothing about the configuration encodes why it was made, which is why the protection has to come from isolating the machine rather than from anything the machine itself can enforce.
Your analysis workstation, as the system sees it
Indistinguishable from a compromiseWhy this is worth sitting with
- A payload fetched the same way carries the same absence of an attribute, so the two are indistinguishable on this property alone.
- You granted the terminal full disk access so parsers could read evidence. Nothing on the machine records that reason.
- Both conditions together mean no block at all and no warning to the user at the moment of execution.
The point is not that your workstation is unsafe. It is that the state you built deliberately is the state you will later find on a victim's machine and have to explain.
That argues for a dedicated workstation rather than a laptop you also read email on. It is a boring recommendation and it follows directly from the mechanism rather than from general caution, which is the only kind of security advice worth taking seriously. The converse is the part people resist: a shared machine cannot be made safe for this work by configuration, because the weakenings that make it useful for analysis are exactly the ones that make it attractive to compromise, and no amount of care about which browser extensions are installed changes that arithmetic.
Isolation also has a second purpose that has nothing to do with attackers. A machine used for nothing else has a configuration small enough to describe completely, which is what the last section of this sub asks you to do. A laptop that also runs a mail client, a browser with extensions and whatever a previous case required is not describable in a paragraph, and a configuration you cannot describe is one you cannot defend. That is the practical argument for a dedicated machine even where the security argument has already been accepted in principle and quietly ignored in practice. Hardware for this need not be expensive, and the cost of the alternative is paid once, in a case, at the worst possible time. A small dedicated machine that does nothing else is within reach of most budgets, and it removes an entire class of argument about whether a finding could have been contaminated by something unrelated that was running at the time.
What stays on, and why
Because not everything should come offKnowing where the removals stop is as much a part of the setup as making them, because the temptation after two sections of weakening is to keep going. Integrity protection is the one to leave alone on the analysis machine. Published description notes it restricts changes to system files even by the root account, and nothing about reading a mounted image requires changing your own system files.
WHAT TO WEAKEN AND WHAT TO LEAVE
weaken, per tool the download attribute, on tools you chose
weaken, per app disk access, for the specific tools that read evidence
leave alone integrity protection on the analysis machine
leave alone anything you cannot state a reason for
the last line is the whole policy
Read the block as a scope rather than a checklist. Each weakening is per tool or per application, and the two that stay are the ones no analysis task actually needs removed.
The mounted evidence is a separate question from your own system files, and conflating the two is what produces unnecessary removals. Reading a subject's protected paths from an image works because the protection applies to the running system rather than to a volume you attached, so the subject's own restrictions are not an obstacle you have to dismantle anything to get past.
That is worth knowing before somebody suggests otherwise under time pressure. The instinct that a protected path on the subject machine requires disabling protection on the analysis machine is common and wrong, and acting on it weakens your own system for no gain at all. If a path on a mounted volume will not open, the cause is the access grant on your reading tool rather than the integrity protection on your host. Checking the grant first costs a moment and rules out the change you would otherwise make for no reason.
The same confusion appears in the other direction when people expect a subject's protections to have been carried into the image. They are not enforcement on a volume you mounted; they were enforcement on a system that is no longer running. What the image preserves is the configuration as a fact to be read, which is evidence about the subject rather than an obstacle to reading it. Whether the subject's protection was enabled or disabled is itself a finding, and it is one you would lose by assuming the image behaves like a running machine.
Recording the configuration
Which the scenario did notRecording what you changed is the cheapest step here and the one the scenario skipped after everything else had gone wrong. Write down what was altered, on which tool, and why. An analysis workstation whose configuration nobody can describe is one whose results nobody can defend, because the first question about any finding is what the machine was doing when it produced it.
THE WORKSTATION RECORD
the tool name, version, where it came from
what was changed the attribute, the signature, the access grant
the scope that bundle, or system-wide
why the refusal it cleared, named
a change with no recorded reason is one nobody can defend later
Read the block as the record a workstation carries. The scope line is the one that matters under challenge: a per-tool repair is a defensible engineering decision, and a global switch with no record is something somebody else has to explain on your behalf.
The reason line does more work than it looks like it does. Naming the refusal a change cleared means that when the same refusal appears on a different tool a year later, the record tells you what worked rather than leaving somebody to rediscover it, and it also tells you which changes can be reversed once a tool is replaced.
The record has one more use at the end of a case rather than the start. When a workstation is rebuilt or handed on, the list is what lets the next person reproduce the environment a finding was produced in, which is occasionally the difference between a result that can be re-examined and one that has to be taken on trust. Keeping it is a few lines per tool and it accumulates into the only description of the machine that will exist. Nobody reconstructs it afterwards, because the changes were individually small enough to forget within a week of making them. That is the honest reason to write them down as you go rather than intending to write them up later. A line typed at the moment of the change costs nothing and is accurate; the same line reconstructed a month later is a guess wearing the authority of a record, and on a machine that produces evidence that distinction matters more than it does anywhere else in the toolkit.
Practice
Diagnose before you repair hands onThe diagnosis is two commands and almost nobody runs them before reaching for the fix.
- Answer the scenario. Name what the damaged message actually meant and say why the global switch was the wrong response.
- State the combination. Say which two facts together produce the block, and what happens when only one is present.
- Draw the boundary. Say which controls you weaken per tool and which you leave alone entirely.
- Now on a Mac you have permission to use, pick an application you downloaded and read its extended attributes and its signing state.
- Then write its two-line record. What it carries, and what you would change if it refused to launch. Doing this on a tool that works is how you learn the commands before you need them under pressure.
Published description states that a browser-downloaded unsigned application shows a message claiming it is damaged when it is not, and that the block follows from a combination: the application still carries the attribute marking it as downloaded and has no signature the assessment can trust. Either fact alone behaves differently. Published guidance names the smallest repair as inspecting the attribute, verifying the signing state, applying a local ad-hoc signature to that one bundle and removing the attribute from that one application, while stating that the point is not to disable security globally. Published research separately found that some archiving and virtualization utilities, and some native command-line tools, do not enforce the attribute, and that a program fetched by a signed system transfer utility does not receive it, so with a terminal holding full disk access the assessment will not block execution or warn.