On macOS, a few lines changed in a property list file can hide an app from the Dock, inject environment variables into a trusted application or quietly launch a program at every login, and none of it needs a new binary. MITRE ATT&CK tracks this as T1647 Plist File Modification, a macOS technique in the Defense Impairment tactic (TA0112). Plists are everywhere on a Mac, so the hard part for defenders is telling a malicious edit from routine preference churn. This guide explains which plist locations and keys matter, how to detect suspicious edits with Endpoint Security and unified log telemetry, how code signing and MDM limit the technique, and how to respond. It is written for macOS administrators, detection engineers and incident responders. For the persistence mechanisms that plists configure, see the T1543 Create or Modify System Process Defensive Guide and the T1547 Boot or Logon Autostart Execution Defensive Guide; this page covers the editing of existing plists that enables them.
Key takeaways
- T1647 is an enabler. ATT&CK describes plist edits used to hide execution, add persistence through launch agents, launch daemons or re-opened applications, or set up dynamic linker hijacking.
- Location matters more than the edit. Writes to
LaunchAgents,LaunchDaemons, an app bundle'sInfo.plistorcom.apple.dock.plistdeserve far more scrutiny than writes elsewhere in~/Library/Preferences. - Signed apps resist Info.plist tampering. An app's
Info.plistis covered by its code signature, so editing it invalidates the signature; verifying signatures turns a quiet edit into a visible failure. - Hardened Runtime is the ATT&CK mitigation. ATT&CK maps M1013 Application Developer Guidance: apps built with Hardened Runtime ignore
DYLD_environment variables unless they carry an exception entitlement. - Correlate write, then run. The ATT&CK analytic pairs a plist modification with a later process launch or service start that references the changed file. That pairing is what separates attacks from preference noise.
How the technique works
ATT&CK v20 (technique version 2.0) describes plists as structured key-value metadata, in XML or binary form, that tell macOS how to handle an application at runtime. Adversaries change key-value pairs to influence system behaviour. The technique has no sub-techniques. Older ATT&CK versions listed a Plist Modification sub-technique under T1547 (T1547.011); it is revoked, so map new detections to T1647.
| Plist target | Key or change described by ATT&CK | Effect | Follow-on technique |
|---|---|---|---|
App bundle Info.plist | LSUIElement set so the app runs as an agent app | Apple defines it as a Boolean marking an agent app that runs in the background and does not appear in the Dock | T1564.003 Hidden Window |
App bundle Info.plist | LSEnvironment dictionary inserted | Apple defines it as environment variables set before launching the app; used to load a library | T1574.006 Dynamic Linker Hijacking |
~/Library/Preferences/com.apple.dock.plist | Malicious application path added | A malicious app appears in the Dock, often in place of or beside a trusted one | User execution and masquerading |
| Launch agent or daemon plists | Commands added or changed for persistence | Program runs at login or boot through launchd | T1543.001 Launch Agent, T1543.004 Launch Daemon |
| Re-opened application state | Entries added so an app relaunches after login | Persistence without a launch agent | T1547.007 Re-opened Applications |
ATT&CK cites the Flashback malware as an example of the LSEnvironment approach. Apple's launchd documentation lists daemon plists in /System/Library/LaunchDaemons and /Library/LaunchDaemons, agents for all users in /System/Library/LaunchAgents and /Library/LaunchAgents, and per-user agents in the user's Library/LaunchAgents folder. The required keys are Label and ProgramArguments, and KeepAlive set to true keeps a job running at all times. An edit to ProgramArguments in an existing, trusted-looking job is harder to spot than a new file, which is why edits deserve their own detection.
Which locations to watch
Use this as your monitored directory list (ATT&CK marks the directory list as a value you tune per environment). Our risk ratings are NHI Mgmt Group judgements based on the privilege each location confers.
| Location | Who can write it | Our risk rating | Notes |
|---|---|---|---|
/Library/LaunchDaemons | Root | High | Jobs run as root at boot. Any edit outside a software install or MDM deployment is suspicious. |
/Library/LaunchAgents | Admin or root | High | Runs for every user at login. |
~/Library/LaunchAgents | The user | High | No elevation needed; a favourite of commodity malware. |
/Applications/*.app/Contents/Info.plist | Admin, or the user for apps they own | High | Edits break the app's code signature. |
~/Library/Preferences/com.apple.dock.plist | The user | Medium | Changes often; alert on new paths outside /Applications or /System/Applications. |
~/Library/Application Support plists | The user | Medium | Includes app-specific settings and login item data; noisy, so use for correlation rather than alerting. |
/System/Library | Protected by System Integrity Protection | Low for edits | SIP makes critical system locations read-only even for administrative processes. A successful edit implies SIP is off, which is itself a finding. |
Detection
ATT&CK detection strategy DET0109 gives one macOS analytic: watch for unexpected plist modifications in persistence or configuration directories, track use of defaults, plutil and text editors on Info.plist files, and correlate modifications with later process launches or service starts that reference the changed plist. The table maps that analytic to telemetry you can collect.
| Signal | Source | What to alert on |
|---|---|---|
File write, create or rename of *.plist in the watched locations | Endpoint Security ES_EVENT_TYPE_NOTIFY_WRITE, NOTIFY_CREATE, NOTIFY_RENAME (through your EDR) | Writes by processes that are not installers, MDM agents or the owning app |
defaults write or plutil changing keys | Process execution events (ES_EVENT_TYPE_NOTIFY_EXEC) with command line | Changes to LSUIElement, LSEnvironment, ProgramArguments, RunAtLoad, KeepAlive or Dock persistent-apps |
| Script interpreters writing plists | Process lineage | Shell, Python or osascript parents writing to launch directories |
| Code signature invalidated | Endpoint Security ES_EVENT_TYPE_NOTIFY_CS_INVALIDATED; scheduled codesign --verify sweeps of /Applications | Any production app whose signature no longer verifies |
| Write followed by launch | Correlation of the above with launchd loads or app launches | A plist edit followed within your time window by execution of a binary the plist names, especially from /tmp, /Users/Shared or hidden directories |
| Login and background item changes | sfltool dumpbtm output collected on a schedule (macOS 13 or later) | New background items not matching your managed rules |
Keys worth a dedicated rule, because legitimate use is rare in managed fleets: LSEnvironment containing DYLD_INSERT_LIBRARIES, launch plists whose ProgramArguments point into user-writable paths, and Dock entries pointing outside application directories. Collection of these events depends on your EDR exposing Endpoint Security data; see the macOS Detection and Response Guide and the EDR Guide.
Reducing noise
- Allow by signer, not by path: exclude writes by your MDM agent, known installers and Apple-signed system processes, identified by team ID or signing identity rather than process name.
- Baseline launch items: keep a fleet-wide inventory of launch agent and daemon labels; an edit to a known label that changes
ProgramArgumentsis higher signal than a new third-party label. - Treat preferences differently: most of
~/Library/Preferenceschanges constantly. Alert only on named high-value files and keys.
Prevention and hardening
| Control | How it limits T1647 | Implementation note |
|---|---|---|
| Hardened Runtime (ATT&CK M1013) | Apple states it protects against code injection and library hijacking, with DYLD_ environment variables blocked unless the app holds com.apple.security.cs.allow-dyld-environment-variables | Required for notarisation. For in-house apps, sign with Hardened Runtime and avoid exception entitlements such as allow-dyld-environment-variables and disable-library-validation. |
| Code signature checks | Info.plist edits invalidate the signature | Keep Gatekeeper on; sweep /Applications with codesign --verify and alert on failures. |
| System Integrity Protection | Keeps critical system locations read-only, even for root | Report SIP status through MDM and treat "disabled" as a compliance failure. |
| Managed login items | Service Management configuration (Managed Login Items) approves known background items by bundle ID, team ID or launchd label | Apple applies this to macOS 13 or later. Approve your own tools by team ID so unknown items stand out to users and to your reporting. |
| Standard user accounts | Users without admin rights cannot write /Library/LaunchDaemons or most app bundles | Use temporary elevation for admin tasks; see macOS Security Guide for Enterprises. |
| Configuration baselines | Enforced settings drift back on the next check-in | Use CIS and mSCP baselines; see the macOS CIS and mSCP Compliance Guide. |
Per-user locations stay writable by the user by design, so prevention there relies on detection and on standard accounts limiting what a compromised user session can reach.
Where identity fits
Plist edits are a common way to keep a credential stealer running. A hidden agent app or a modified launch agent can harvest browser sessions, keychain items and developer tokens at every login; the Atomic macOS Stealer Guide covers that family. Launch plists can also carry secrets themselves: the EnvironmentVariables key in a launch daemon is sometimes used to pass API keys to background services. Keep secrets out of plists, read them from the keychain or a secrets manager at runtime, and treat any secret found in a modified plist as exposed.
Response
- Preserve: copy the modified plist, the original if a backup or known-good copy exists, the binary it references, and the unified log and EDR events around the change. The macOS Forensics Guide lists further artefacts.
- Identify the writer: use process lineage to find what made the edit and how it got there.
- Contain: unload the job with
launchctl, isolate the host through EDR, and block the referenced binary by hash or team ID. - Restore: replace modified app bundles from a trusted source rather than editing them back; restore Dock and preference plists from a known-good copy or reset them.
- Rotate: revoke browser sessions and rotate credentials and tokens that were usable on the host while the persistence was active.
- Hunt: search the fleet for the same label, key value or referenced path.
Implementation sequence
The phases and timings below are NHI Mgmt Group recommendations; adjust them to your estate.
- Inventory (weeks 1 to 2): collect launch agent and daemon labels and
ProgramArgumentsacross the fleet, plus SIP status and signature status of installed apps. - Enable telemetry (weeks 2 to 4): confirm your EDR records Endpoint Security file and exec events for the watched locations.
- Pilot rules in alert-only mode (weeks 3 to 6): deploy the write, key and correlation rules to an IT pilot group, add signer-based exclusions, then widen.
- Harden (weeks 4 to 8): deploy managed login item rules for approved tools, enforce standard accounts and report SIP and Gatekeeper status.
- Rollback: if a rule floods the queue, drop it back to logging only and tune exclusions; test managed login item payload changes on the pilot group before fleet-wide removal or replacement.
Decision guidance and measurement
- Small fleets: start with launch directory monitoring and signature sweeps; they catch most commodity persistence with little tuning.
- Large or developer-heavy fleets: developers legitimately use
defaultsand edit plists, so lean on correlation and signer-based exclusions rather than tool-name rules. - Metric: percentage of Macs reporting Endpoint Security file events for watched locations (target 100%).
- Metric: number of unknown launch labels across the fleet, trending down.
- Metric: number of production apps failing signature verification (target zero).
- Metric: percentage of Macs with SIP enabled (target 100%).
Common failure patterns
- Watching new files only: rules that fire on new launch plists miss an edit to an existing, trusted label.
- Excluding by process name: attackers name helpers after updaters; exclude by signing identity instead.
- Ignoring signature failures: an invalid signature on a business app is treated as a packaging glitch rather than possible tampering.
- Admin by default: users with permanent admin rights can write system-wide launch locations and app bundles.
- Cleaning the plist but not the payload: removing the job while leaving the binary and stolen sessions in place.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| MITRE ATT&CK | T1647; TA0112; M1013; DET0109 | Technique, tactic, mitigation and detection strategy |
| MITRE ATT&CK | T1543.001, T1543.004, T1547.007, T1564.003, T1574.006 | Follow-on techniques enabled by plist edits |
| NIST SP 800-53 Rev 5 | CM-3 Configuration Change Control; CM-6 Configuration Settings | Controlled, baselined configuration |
| NIST SP 800-53 Rev 5 | SI-7 Software, Firmware, and Information Integrity; SI-4 System Monitoring | Signature checks and monitoring of plist changes |
| NIST CSF 2.0 | PR.PS-01; DE.CM-09 | Configuration management; monitoring of software and runtime environments |
Practitioner checklist
- Monitor writes to launch agent and daemon directories, app bundle Info.plist files and the Dock plist.
- Alert on
LSEnvironment,LSUIElementandProgramArgumentschanges outside approved deployments. - Correlate plist writes with later launches of the binaries they reference.
- Exclude noise by signing identity, never by process name.
- Sweep installed apps for invalid code signatures and investigate failures.
- Report SIP and Gatekeeper status from every Mac.
- Approve your own background items with managed login item rules.
- Keep users on standard accounts and keep secrets out of plists.
Standards and references
- MITRE ATT&CK: Plist File Modification (T1647)
- Apple Developer: LSEnvironment
- Apple Developer: LSUIElement
- Apple Developer: Hardened Runtime
- Apple Developer: Endpoint Security event types
- Apple Developer: Creating Launch Daemons and Agents
- Apple Platform Deployment: Manage login items and background tasks on Mac
- Apple Platform Security: System Integrity Protection
Related NHI Mgmt Group resources: macOS Detection and Response Guide · macOS LOOBins · T1543 Create or Modify System Process Defensive Guide · ATT&CK Stealth and Defense Impairment Tactics Guide · macOS Forensics Guide