Skip to content

Fixing protected settings key leak#2198

Open
jaytripath wants to merge 1 commit into
masterfrom
mrtripathi/fixprotectedsettingsleak
Open

Fixing protected settings key leak#2198
jaytripath wants to merge 1 commit into
masterfrom
mrtripathi/fixprotectedsettingsleak

Conversation

@jaytripath

Copy link
Copy Markdown
Contributor

Fixes a security incident where the decrypted protectedSettings value was leaked into extension logs.

Root cause:
On VMs where OpenSSL is misconfigured (missing /usr/local/ssl/openssl.cnf), openssl cms/smime prints a non-fatal warning to stderr. Because stderr was merged into the same stream as the decrypted stdout, the warning text got prepended to the decrypted JSON, breaking json.loads(). The resulting exception handler in HandlerUtil.py then logged the raw decrypted payload through redact_protected_settings() — but that helper only strips the outer, still-encrypted envelope fields (protectedSettings, protectedSettingsCertThumbprint); it doesn't recognize secrets inside the already-decrypted payload (e.g. workspaceKey), so the redaction was a silent no-op and the raw key was logged in plaintext.

Separately, agent.py's Install operation could crash outright (exit code 1) if logrotate.d doesn't exist on the VM, since the logrotate-config copy wasn't guarded against that failure.

Changes:

  • HandlerUtil.py — _parse_config():

On JSON-decode failure of the decrypted protectedSettings, stop logging the (ineffectively "redacted") raw payload. Log only the exception message instead, which never contains the original content.

  • agent.py — get_settings():

Changed the OpenSSL decrypt subprocess to capture stderr separately (subprocess.PIPE) instead of merging it into stdout (subprocess.STDOUT). Prevents non-fatal OpenSSL warnings from corrupting the JSON payload and causing decode failures in the first place — hardening the equivalent decrypt path used by Enable/metrics/syslog/transform-config operations.

  • agent.py — parse_context():

Wrapped the logrotate config copyfile() in a try/except (mirroring the existing pattern for the sibling os.remove() call), so a missing logrotate.d directory logs a warning instead of failing the entire Install operation with exit code 1.

Work-item:
https://dev.azure.com/msazure/One/_workitems/edit/38590195

@jaytripath
jaytripath requested review from a team, D1v38om83r and nkuchta as code owners July 23, 2026 20:36
@jaytripath jaytripath self-assigned this Jul 23, 2026
@jaytripath

Copy link
Copy Markdown
Contributor Author

@microsoft-github-policy-service agree company="Microsoft"

@jaytripath
jaytripath requested a review from simathih July 23, 2026 21:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant