Agent Tamper Protection

Tamper protection makes the Hermes agent hard to stop or uninstall on the machines you manage, and tells you when someone tries. While it is on, a local administrator cannot simply stop or delete the agent service, the agent's files are protected, and the only sanctioned local uninstall needs a single-use code that Athena issues for that one machine. Tamper attempts, uses of a code, and an agent that disappears right after either one show up on the Alerts board and in the audit log. Everything runs on your own server, so it works on an air-gapped network.

Scope
  • Off by default. Nothing changes on any agent until an administrator turns it on.
  • Fleet-wide. One switch covers every Windows, Linux and macOS agent connected to the server. You cannot turn it on for some collections only.
  • It raises the bar; it does not make removal impossible. A determined local administrator or root user can still defeat it (see Limits). What tamper protection guarantees is that ordinary stop and uninstall attempts fail, and that the attempt becomes visible in Athena.

Turning it on#

  1. Open Settings → Agents → Configuration.
  2. In the Tamper Protection section, tick Enable tamper protection.
  3. Click Save at the bottom of the page.

The change is pushed straight away to every connected agent. Agents that are offline pick it up the next time they connect, because the setting is sent on every connect. Each agent applies its protections once per change, so saving the page again does not re-run them.

To turn it off, clear the box and save. Each agent then removes its protections and goes back to its normal state (see the table below).

The setting is stored as Agent:TamperProtectionEnabled in the server's appsettings.json (see Configuration).

What it does on each OS#

OSWhile tamper protection is onWhen it is turned off
Windows
  • Local Administrators can still query and start the agent service, but they cannot stop, pause, delete or reconfigure it. Other users can only read it. The local SYSTEM account keeps full control.
  • The agent's install folder becomes read and execute only for Administrators.
  • Attempts to stop or delete the service are set to be audited in the Windows Security log. These entries only appear if Object Access auditing is enabled in your audit policy. Athena's own detection does not rely on them.
  • If the service dies, Windows restarts it after 5 seconds, then 5 seconds, then 60 seconds. The failure count resets after one day.
The default service permissions and audit settings are restored. The install folder's permissions are reset. Service recovery goes back to restart after 5 seconds, three times.
Linux
  • The agent binary /opt/hermes/Hermes.Agent and /opt/hermes/appsettings.json are made immutable (chattr +i). Even root cannot change or delete them without removing the flag first.
  • A systemd drop-in sets Restart=always on the hermes-agent service, so a plain systemctl stop is undone.
The immutable flags are removed and the drop-in is deleted. The service's normal restart behaviour stays.
macOS
  • /Library/Application Support/Hermes/Hermes.Agent and /Library/Application Support/Hermes/appsettings.json get the system immutable flag (chflags schg).
  • launchd already restarts the agent if it stops.
The immutable flags are removed. The launchd restart behaviour stays.

Limits#

Tamper protection is a deterrent and an alarm, not a lock. Someone with full control of a machine can still remove the agent. For example, a Windows administrator can take back ownership of the install folder, disable the service in the registry, or run commands as SYSTEM. A Linux or macOS root user can clear the immutable flags. When that happens, the self-check and the Agent removed unexpectedly alert are what make the attempt visible.

How tampering is detected#

Agents report these events to Athena:

If the agent is offline when an event happens, the event is queued on the machine. It is sent the next time the agent connects.

Uninstall codes#

An uninstall code authorises one uninstall of the agent on one machine. Each code:

You only need a code while tamper protection is on. With protection off, the uninstall command runs without one.

Issuing a code in the console#

  1. Open the agent's Agent Details page.
  2. In the header, click the shield icon ("Issue a single-use uninstall code for this agent (needed only while tamper protection is on)"). It sits next to the revoke icon.
  3. Confirm with Issue code. The dialog warns that whoever holds the code can uninstall the agent on that machine until it expires.
  4. The code is shown once, with its expiry time. Copy it with the copy icon. When you close the dialog, it cannot be shown again. Issue a new one if you lose it.

Issuing a code requires the agents.revoke permission, which only the built-in Admin role has. Without it, the shield icon is hidden. The icon is also hidden on a revoked agent. Every issued code is audited. The code itself is never written to the audit log; it is identified by its last four characters only.

Uninstalling a protected agent#

The sanctioned local uninstall is the uninstall command of the HermesCLI, which every agent places next to itself. Run it from an elevated (Administrator) prompt on Windows, or as root on Linux and macOS:

hermescli uninstall --code <CODE> [--purge]

hermescli is on the PATH on every OS (see HermesCLI on PATH). You can also call the CLI by its full path:

OSCommand
Windows (elevated prompt)HermesCLI.exe uninstall --code <CODE>, run from the agent's install folder
Linuxsudo /opt/hermes/HermesCLI uninstall --code <CODE>
macOSsudo "/Library/Application Support/Hermes/HermesCLI" uninstall --code <CODE>
OptionMeaning
--code <CODE> (alias --uninstall-code)The uninstall code issued by Athena. Required only while tamper protection is on.
--purgeAlso remove the configuration, data, certificates and logs. Without it, these are kept.

The command checks whether the machine is protected by looking at the protections themselves. If they are in place, it removes them first, then removes the agent. Before it removes anything, it prints the list of what it will remove.

What is removed#

OSWithout --purgeWith --purge
WindowsThe HermesAgent service and every file in the install folder except appsettings*.json.Also the install folder itself and C:\ProgramData\Hermes (data, certificates and logs).
LinuxThe hermes-agent systemd unit and its drop-in folder, and everything in /opt/hermes except appsettings*.json.Also /opt/hermes and /var/lib/hermes (logs are inside it).
macOSThe com.athena.hermes-agent LaunchDaemon and the agent and CLI executables only. The install folder is also the data folder, so everything else in it stays.Also /Library/Application Support/Hermes and /Library/Logs/Hermes.

If the agent's Agent:DataPath is set in the install folder's appsettings.json, that folder is used as the data folder. The hermescli PATH entry (Windows) or the /usr/local/bin/hermescli link (Linux, macOS) is removed as well.

On Windows the removal runs as SYSTEM through a one-time scheduled task, because the protected service cannot be stopped by Administrators. The command returns straight away and prints "The service is being stopped and removed as SYSTEM; the files above are gone within ~15 seconds."

How Athena learns about it#

The command hands the event (authorised or refused) to the running agent service, and waits up to 5 seconds for the agent to send it to Athena. It prints "Athena notified (…)" when the event was sent. If the agent is not running or not connected, it prints "Athena not notified yet …" and continues. The event then stays queued in the data folder unless --purge removes it. An uninstall on an unprotected machine without a code is not a tamper event and is not reported.

Messages and exit codes#

Any non-zero exit code other than 1 means nothing was removed.

Exit codeMessageMeaning
0"Uninstall code accepted (server '…')." or "Tamper protection is off on this machine; no uninstall code is needed."The uninstall went ahead.
1"Failed: could not schedule the SYSTEM teardown …" (Windows) or "could not remove …" lines (Linux, macOS)The removal could not be started (Windows, nothing was removed), or some items could not be removed (Linux, macOS).
2"Run this from an elevated (Administrator) prompt." / "Run this as root (sudo)."Not elevated.
3"Tamper protection is on: an uninstall code is required. …"No --code was given.
4"The uninstall code has expired. Issue a new one."
"The uninstall code was already used. Issue a new one."
"The uninstall code was issued for a different agent."
"The uninstall code is not signed by this agent's Athena CA."
"The uninstall code is not valid."
"Tamper protection is on but this agent holds no enrolment (agent id + CA certificate) to verify the code against."
The code was refused.

An agent enrolled with more than one server accepts a code issued by any of them.

Alerts#

Tamper events raise alerts on the Alerts board, tied to the agent. They count in the agent's alert badge and can be filtered by agent like any other alert. One alert is kept per agent and condition: a repeat event updates the existing open alert (its count and last-seen time) instead of adding a new row.

AlertSeverityRaised when
Tamper detectedCriticalThe agent reported protections removed, or a refused uninstall.
Uninstall code usedWarningThe agent accepted a valid uninstall code.
Agent removed unexpectedlyCritical, or Warning after a valid codeThe agent went offline right after one of the events above and did not come back (see below).

Agent removed unexpectedly is raised only for an agent that has just reported a tamper event or a code use, so a normal reboot or shutdown never raises it. It fires when the agent's last heartbeat falls within 15 minutes of the event and the agent has then been offline for at least 10 minutes. A machine that reboots and comes back within those 10 minutes does not raise it. After a valid code it is only a Warning, because a sanctioned uninstall looks the same. The watch for this alert is kept in memory, so if the Athena server restarts during that window, the alert is not raised. The tamper alert itself is not affected. Removing the agent from Athena also ends the watch.

Audit events#

These event types appear in the audit log:

Event typeSeverityWritten when
AgentUninstallCodeIssuedWarningA code was issued. Records who issued it, the agent, the expiry, and the code's last four characters.
AgentUninstallCodeUsedWarningAn agent reported that it accepted a valid code and is uninstalling.
AgentTamperDetectedCriticalAn agent reported a tamper attempt. The action column holds the kind of event (for example SelfProtectionRemoved or UninstallRefused), and the description holds the detail.
AgentRemovedUnexpectedlyCritical, or Warning after a valid codeAn agent went offline right after a tamper event or code use and did not come back.

Configuration#

These keys go in the server's appsettings.json, or in environment variables using __ for : (for example Tamper__UninstallCodeTtlMinutes=30). See Configuration.

KeyDefaultEffect
Agent:TamperProtectionEnabledfalseThe fleet-wide switch. Normally set from Settings → Agents → Configuration.
Tamper:UninstallCodeTtlMinutes60How long an issued code stays valid when no validity is given. Always kept between 5 and 1440 minutes.
Tamper:RemovalWindowMinutes15For Agent removed unexpectedly: the agent's last heartbeat must fall within this many minutes after the event.
Tamper:OfflineGraceMinutes10…and it must then stay offline this long before the alert is raised.
Tamper:WatchIntervalSeconds60How often the server checks watched agents. Minimum 5.

REST API#

Codes can also be issued over the REST API (see API Reference and API Tokens). The response uses Athena's usual envelope, with the result in data.

Method & pathPermissionDescription
POST /api/agents/{id}/uninstall-codeagents.revokeIssues a code for the agent. Optional query ttlMinutes (kept between 5 and 1440; default from Tamper:UninstallCodeTtlMinutes). 200 with data = { "agentId", "code", "expiresAt" }; 404 no such agent; 403 missing permission.
curl -k -X POST -H "Authorization: Bearer <token>" \
  "https://<server>:8443/api/agents/<agent-id>/uninstall-code?ttlMinutes=30"

PowerShell#

The Athena PowerShell module has New-AthenaAgentUninstallCode. It asks for confirmation unless you pass -Force. The returned Code is sensitive.

ParameterDescription
-IdThe agent's id (mandatory; accepted from the pipeline by property name).
-TtlMinutesValidity in minutes, 5–1440. Omit it for the server default.
-ForceIssue without confirmation.
Get-AthenaAgent -Hostname "LAB-PC" | New-AthenaAgentUninstallCode -TtlMinutes 30

Troubleshooting#

SymptomWhat to check
No shield icon on Agent DetailsYour role lacks agents.revoke (Admin only by default), or the agent is revoked.
sc stop HermesAgent fails with "Access is denied" for an administratorExpected while tamper protection is on. Use hermescli uninstall with a code, or turn protection off and wait for the agent to apply the change.
Uninstall says the code has expired, but it was just issuedThe machine checks the expiry against its own clock. Check the machine's date and time, then issue a new code.
Uninstall says the code is for a different agent or not signed by this agent's CAThe code was issued for another machine, or by an Athena server this agent is not enrolled with. Issue the code from this machine's own Agent Details page.
"… this agent holds no enrolment …"The agent's enrolment files are missing from its data folder. Reconnect the agent to Athena (it restores a missing agent id from the server on connect), or re-enrol it.
A refused or authorised uninstall did not appear in AthenaThe agent was not running or not connected. The event is sent when the agent next connects, unless --purge removed it.
Tamper detected appeared, but nobody touched the machineOpen the alert or the AgentTamperDetected audit entry to see the event kind and detail. SelfProtectionRemoved means the agent found its protections changed during its self-check and put them back.