Summary
The _validate_key_file helper in azure/identity/_credentials/azure_arc.py validates the key file path returned by the HIMDS WWW-Authenticate header before reading it. The current checks are purely lexical and do not account for symbolic links. Adding symlink resolution would strengthen defense-in-depth.
Current behavior
_validate_key_file performs the following checks on the raw file_path string:
os.path.exists(file_path) -- confirms the path exists.
os.path.dirname(file_path) == _get_key_file_path() -- lexical comparison of the parent directory.
file_path.endswith(".key") -- extension check.
os.path.getsize(file_path) <= 4096 -- size cap.
Because step 2 compares the unresolved path, a symbolic link such as /var/opt/azcmagent/tokens/malicious.key -> /etc/shadow would pass all four checks despite the real target residing outside the trusted directory.
Proposed enhancement
Before performing the directory comparison, resolve the path to its canonical form:
resolved = os.path.realpath(file_path)
Then validate the resolved path:
expected_directory = _get_key_file_path()
if os.path.dirname(resolved) != expected_directory:
raise ValueError(f"Unexpected file path from HIMDS service: {file_path}")
Additionally, consider checking via os.lstat that the file is a regular file (not a symlink, device node, FIFO, etc.):
import stat
file_stat = os.lstat(file_path)
if stat.S_ISLNK(file_stat.st_mode):
raise ValueError("Key file must not be a symbolic link.")
if not stat.S_ISREG(file_stat.st_mode):
raise ValueError("Key file must be a regular file.")
Risk assessment
This is not a remotely exploitable vulnerability. Exploitation requires:
- Local filesystem access with sufficient privileges to create a symlink in the trusted directory (
/var/opt/azcmagent/tokens on Linux or the PROGRAMDATA\AzureConnectedMachineAgent\Tokens directory on Windows).
- These directories are already restricted to privileged accounts by the Azure Connected Machine Agent installer.
The enhancement is proposed as defense-in-depth to reduce risk in scenarios where directory permissions are inadvertently relaxed or an attacker has partial local access.
Affected file
Summary
The
_validate_key_filehelper inazure/identity/_credentials/azure_arc.pyvalidates the key file path returned by the HIMDSWWW-Authenticateheader before reading it. The current checks are purely lexical and do not account for symbolic links. Adding symlink resolution would strengthen defense-in-depth.Current behavior
_validate_key_fileperforms the following checks on the rawfile_pathstring:os.path.exists(file_path)-- confirms the path exists.os.path.dirname(file_path) == _get_key_file_path()-- lexical comparison of the parent directory.file_path.endswith(".key")-- extension check.os.path.getsize(file_path) <= 4096-- size cap.Because step 2 compares the unresolved path, a symbolic link such as
/var/opt/azcmagent/tokens/malicious.key -> /etc/shadowwould pass all four checks despite the real target residing outside the trusted directory.Proposed enhancement
Before performing the directory comparison, resolve the path to its canonical form:
Then validate the resolved path:
Additionally, consider checking via
os.lstatthat the file is a regular file (not a symlink, device node, FIFO, etc.):Risk assessment
This is not a remotely exploitable vulnerability. Exploitation requires:
/var/opt/azcmagent/tokenson Linux or thePROGRAMDATA\AzureConnectedMachineAgent\Tokensdirectory on Windows).The enhancement is proposed as defense-in-depth to reduce risk in scenarios where directory permissions are inadvertently relaxed or an attacker has partial local access.
Affected file
sdk/identity/azure-identity/azure/identity/_credentials/azure_arc.py--_validate_key_filefunction.