Azure / Azure/azure-sdk-for-python
[Azure.Identity] Add symlink-aware validation to Azure Arc key file path checks
- Dominant language
- Python
- Stars
- 5.6k
- Forks
- 3.4k
- Avg merge
- 1d 21h
- Merged PRs (30d)
- 193
Description
### 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:
1. `os.path.exists(file_path)` -- confirms the path exists.
2. `os.path.dirname(file_path) == _get_key_file_path()` -- lexical comparison of the parent directory.
3. `file_path.endswith(".key")` -- extension check.
4. `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:
```python
resolved = os.path.realpath(file_path)
```
Then validate the **resolved** path:
```python
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.):
```python
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
- [`sdk/identity/azure-identity/azure/identity/_credentials/azure_arc.py`](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/identity/azure-identity/azure/identity/_credentials/azure_arc.py) -- `_validate_key_file` function.
Contributor guide
Assessment
This issue has not been assessed yet.