mirror of
https://github.com/rmcrackan/Libation.git
synced 2026-09-12 21:57:19 -04:00
This is the reported leak. AuthenticationRequiredException held the live
Account, and Serilog.Exceptions writes every public property of a logged
exception into the log file - following nested objects as it goes - so
pausing auto-scan wrote the reporter's real address into a file we ask
people to attach to public issues. Their DecryptKey happened to be empty;
with activation bytes set it would have published those too.
The exception now carries an AccountSummary: masked entry and a
credentials flag, both safe to log, plus the owner-facing label behind a
method rather than a property, because reflection reads properties and
never calls methods. The constructor still takes an Account, so callers
and tests are unchanged.
The thrown message named the account too, and it reaches the log twice -
once as {Exception}, once as ExceptionDetail.Message - so it is masked
now. The GUI dialog still shows the full name and address, since that is
the owner's own screen. For the CLI, stderr is not teed into Serilog, so
that is where a headless user is told which account in full.
Two tests, one for the bug and one for the class of bug: the first logs a
real exception through the same WithExceptionDetails enricher Libation
configures and asserts no address, activation bytes, tokens, or cookies
come out. The second walks the public property graph of every exception
type in these assemblies and fails if one can reach an Account or an
Identity. Restoring the old property makes all of it fail, naming
"jade@example.com" and the path AuthenticationRequiredException.Account.
Co-authored-by: rmcrackan <rmcrackan@gmail.com>
20 lines
940 B
C#
20 lines
940 B
C#
namespace AudibleUtilities;
|
|
|
|
/// <summary>
|
|
/// Stored Audible credentials are missing or invalid and interactive login is required.
|
|
/// Thrown instead of opening login UI when the caller disallows interactive login (e.g. auto-scan).
|
|
/// </summary>
|
|
public sealed class AuthenticationRequiredException : Exception
|
|
{
|
|
/// <summary>
|
|
/// A log-safe summary rather than the <see cref="Account"/> itself. Serilog.Exceptions reflects over every
|
|
/// public property of a logged exception, so holding the live account published its address - and would have
|
|
/// published its activation bytes - into logs people attach to public issue reports.
|
|
/// </summary>
|
|
public AccountSummary? AccountInfo { get; }
|
|
|
|
public AuthenticationRequiredException(Account? account, string? message = null, Exception? innerException = null)
|
|
: base(message ?? "Audible authentication is required.", innerException)
|
|
=> AccountInfo = AccountSummary.From(account);
|
|
}
|