You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add source tag to Write-Log cmdlet output to prevent log forgery #1455
The Write-Log cmdlet passes user-provided content directly to PowerShellLog methods without sanitization or source tagging. When JSON format logging is enabled, a script author can craft log entries that are structurally indistinguishable from system-generated events:
This produces a JSON log entry that a SIEM/Splunk parser interprets as a genuine successful admin login.
Practical impact: Low. The attacker must have script execution privileges. However, in multi-author environments, a lower-privileged script author could forge audit entries to cover malicious activity.
Implementation Plan
Add a source field to differentiate script-authored log entries:
protectedoverridevoidProcessRecord(){vartaggedMessage=$"[Script] source=user-script {LogString}";switch(LogLevel){case"info":PowerShellLog.Info(taggedMessage);break;// ... other levels}}
The [Script] prefix and source=user-script key ensure SIEM parsers can filter or flag script-authored entries.
Files to modify
File
Change
src/Spe/Commands/Diagnostics/WriteLogCommand.cs
Add source=user-script tag to all log output
Test Plan
Unit test — Write-Log output includes source tag: Call Write-Log "test" → log contains source=user-script.
Unit test — system events do NOT contain source tag.
SIEM filter test: Configure query that excludes source=user-script — verify system events pass, script events filtered.
Recommendation: Sanitize \r and \n from user messages before logging to prevent tag bypass via line splitting.
2. Tag format
The [SPE] prefix in PowerShellLog only applies when the PowerShellExtensionsFileAppender is missing - in standard deployments the appender is configured in Spe.config (line 400), so messagePrefix is empty. There is no existing prefix convention to follow in the SPE log file.
SPE system logs already use [Category] key=value format (e.g., [Session] action=scriptExecuting). The tag should follow this pattern:
Key-value mode: Prepend [Script] to user messages
JSON mode: Add "source":"script" as a structured field, set before parsing user content so it cannot be overwritten (ToJson uses first-match-wins for duplicate keys)
3. Other log forgery vectors
Two additional paths where user-controlled content reaches PowerShellLog:
Path
Risk
Notes
ScriptingHostUserInterface.WriteToLog()
Low
Logs Write-Host, Write-Warning, etc. output. Gated by Spe.OutputLoggingEnabled which defaults to false. Exploitable only when explicitly enabled.
ScriptSession line 823
Minimal
Logs entire script body at DEBUG level before execution. Only fires when log level is set to DEBUG (default is INFO). Diagnostics path, not user output.
ScriptSession lines 982/990
Minimal
Logs error records from script execution. Crafting specific exception messages for log forgery is impractical.
Recommendation: Tag Write-Log only for this issue. If Spe.OutputLoggingEnabled tagging is desired, handle as a separate follow-up.
4. WriteVerbose output
WriteLogCommand.LogString() also calls WriteVerbose(message). The verbose stream goes to PowerShell's pipeline (visible only to the script author in their session), not to Sitecore logs. The source tag should not be applied to verbose output.
5. Scope summary
For this issue:
Modify WriteLogCommand.LogString() to prepend [Script] tag
Sanitize newlines (\r, \n) from user messages before logging
In JSON mode, inject "source":"script" field before user content parsing
Activity
michaellwest commentedon Apr 14, 2026
Additional Considerations from Investigation
1. Newline injection bypass
Even with a source tag, a user can embed newlines to produce a second log line without the tag:
Recommendation: Sanitize
\rand\nfrom user messages before logging to prevent tag bypass via line splitting.2. Tag format
The
[SPE]prefix inPowerShellLogonly applies when thePowerShellExtensionsFileAppenderis missing - in standard deployments the appender is configured inSpe.config(line 400), somessagePrefixis empty. There is no existing prefix convention to follow in the SPE log file.SPE system logs already use
[Category] key=valueformat (e.g.,[Session] action=scriptExecuting). The tag should follow this pattern:[Script]to user messages"source":"script"as a structured field, set before parsing user content so it cannot be overwritten (ToJson uses first-match-wins for duplicate keys)3. Other log forgery vectors
Two additional paths where user-controlled content reaches
PowerShellLog:ScriptingHostUserInterface.WriteToLog()Write-Host,Write-Warning, etc. output. Gated bySpe.OutputLoggingEnabledwhich defaults tofalse. Exploitable only when explicitly enabled.ScriptSessionline 823ScriptSessionlines 982/990Recommendation: Tag
Write-Logonly for this issue. IfSpe.OutputLoggingEnabledtagging is desired, handle as a separate follow-up.4. WriteVerbose output
WriteLogCommand.LogString()also callsWriteVerbose(message). The verbose stream goes to PowerShell's pipeline (visible only to the script author in their session), not to Sitecore logs. The source tag should not be applied to verbose output.5. Scope summary
For this issue:
WriteLogCommand.LogString()to prepend[Script]tag\r,\n) from user messages before logging"source":"script"field before user content parsingWriteVerboseuntagged