diff --git a/microsoft/knowledge/privacy/getlasterrortext-customer-content-in-errors.bad.al b/microsoft/knowledge/privacy/getlasterrortext-customer-content-in-errors.bad.al index 838cb26..432aee9 100644 --- a/microsoft/knowledge/privacy/getlasterrortext-customer-content-in-errors.bad.al +++ b/microsoft/knowledge/privacy/getlasterrortext-customer-content-in-errors.bad.al @@ -5,7 +5,7 @@ codeunit 50209 "Privacy Sample GetLastError Bad" AttachmentFailedErr: Label 'Attachment failed: %1', Comment = '%1 = underlying error'; begin if not TryAddAttachment() then - Error(StrSubstNo(AttachmentFailedErr, GetLastErrorText(true))); + Error(StrSubstNo(AttachmentFailedErr, GetLastErrorText())); end; procedure AddAttachmentWithConcatenation() @@ -13,7 +13,7 @@ codeunit 50209 "Privacy Sample GetLastError Bad" AttachmentFailedErr: Label 'Attachment failed: '; begin if not TryAddAttachment() then - Error(AttachmentFailedErr + GetLastErrorText(true)); + Error(AttachmentFailedErr + GetLastErrorText()); end; [TryFunction] diff --git a/microsoft/knowledge/privacy/getlasterrortext-customer-content-in-errors.good.al b/microsoft/knowledge/privacy/getlasterrortext-customer-content-in-errors.good.al index fabec42..ff63592 100644 --- a/microsoft/knowledge/privacy/getlasterrortext-customer-content-in-errors.good.al +++ b/microsoft/knowledge/privacy/getlasterrortext-customer-content-in-errors.good.al @@ -5,7 +5,7 @@ codeunit 50208 "Privacy Sample GetLastError Good" AttachmentFailedErr: Label 'Failed to add the attachment: %1', Comment = '%1 = underlying error shown to the user'; begin if not TryAddAttachment() then - Error(AttachmentFailedErr, GetLastErrorText(true)); + Error(AttachmentFailedErr, GetLastErrorText()); end; [TryFunction] diff --git a/microsoft/knowledge/privacy/getlasterrortext-customer-content-in-errors.md b/microsoft/knowledge/privacy/getlasterrortext-customer-content-in-errors.md index 1bf6f3c..8ff26a8 100644 --- a/microsoft/knowledge/privacy/getlasterrortext-customer-content-in-errors.md +++ b/microsoft/knowledge/privacy/getlasterrortext-customer-content-in-errors.md @@ -11,16 +11,16 @@ application-area: [all] ## Description -`GetLastErrorText()` can contain customer content such as field values, record keys, and file names. When it is passed as a substitution value to an `Error` whose first argument is a `Label` or `TextConst`, the label supplies the Error method trace telemetry message. If `StrSubstNo` or concatenation makes `GetLastErrorText()` part of the first argument, the actual dynamic string is not emitted as that telemetry message; telemetry uses generic guidance instead. +Parameterless `GetLastErrorText()` can contain customer content such as field values, record keys, and file names. The Boolean overload names its parameter `ExcludeCustomerContent`; passing `true` requests scrubbed text and is not the customer-content scenario covered here. When unsanitized error text is passed as a substitution value to an `Error` whose first argument is a `Label` or `TextConst`, the label supplies the Error method trace telemetry message. ## Best Practice -Use a generic label when the user does not need the underlying detail. If showing the detail is appropriate, put `%1` in a label and pass `GetLastErrorText()` as a separate argument. This preserves a useful static telemetry message while keeping the dynamic value out of the telemetry message field. +Use a generic label when the user does not need the underlying detail. If showing unsanitized detail is appropriate, put `%1` in a label and pass parameterless `GetLastErrorText()` as a separate argument. This preserves a useful static telemetry message while keeping the dynamic value out of the telemetry message field. See sample: `getlasterrortext-customer-content-in-errors.good.al`. ## Anti Pattern -`Error(StrSubstNo(AttachmentFailedErr, GetLastErrorText(true)))` or `Error(AttachmentPrefixErr + GetLastErrorText(true))`. Both lose the static first argument and trigger AA0231; neither causes the composed text to be logged verbatim as the Error telemetry message. +`Error(StrSubstNo(AttachmentFailedErr, GetLastErrorText()))` or `Error(AttachmentPrefixErr + GetLastErrorText())`. Both lose the static first argument and trigger AA0231; neither causes the composed text to be logged verbatim as the Error telemetry message. See sample: `getlasterrortext-customer-content-in-errors.bad.al`. diff --git a/microsoft/knowledge/security/secretstrsubstno-for-composing-secrets.bad.al b/microsoft/knowledge/security/secretstrsubstno-for-composing-secrets.bad.al index 14def51..7ff4232 100644 --- a/microsoft/knowledge/security/secretstrsubstno-for-composing-secrets.bad.al +++ b/microsoft/knowledge/security/secretstrsubstno-for-composing-secrets.bad.al @@ -2,7 +2,7 @@ codeunit 50212 "Sec Sample SecretSubst Bad" { procedure BuildAuthHeader(Token: Text): Text begin - exit(StrSubstNo('Bearer %1', Token)); + exit(StrSubstNo('Token %1', Token)); end; procedure BuildSecretUri(ApiKey: Text): Text @@ -12,6 +12,6 @@ codeunit 50212 "Sec Sample SecretSubst Bad" procedure BuildBrokenAuthHeader(Token: SecretText): SecretText begin - exit(SecretStrSubstNo('Bearer', Token)); + exit(SecretStrSubstNo('Token', Token)); end; } diff --git a/microsoft/knowledge/security/secretstrsubstno-for-composing-secrets.good.al b/microsoft/knowledge/security/secretstrsubstno-for-composing-secrets.good.al index 04c0123..0ef1282 100644 --- a/microsoft/knowledge/security/secretstrsubstno-for-composing-secrets.good.al +++ b/microsoft/knowledge/security/secretstrsubstno-for-composing-secrets.good.al @@ -2,7 +2,7 @@ codeunit 50211 "Sec Sample SecretSubst Good" { procedure BuildAuthHeader(Token: SecretText): SecretText begin - exit(SecretStrSubstNo('Bearer %1', Token)); + exit(SecretStrSubstNo('Token %1', Token)); end; procedure BuildSecretUri(ApiKey: SecretText): SecretText diff --git a/microsoft/knowledge/security/secretstrsubstno-for-composing-secrets.md b/microsoft/knowledge/security/secretstrsubstno-for-composing-secrets.md index 060fde0..4c0fa41 100644 --- a/microsoft/knowledge/security/secretstrsubstno-for-composing-secrets.md +++ b/microsoft/knowledge/security/secretstrsubstno-for-composing-secrets.md @@ -11,7 +11,7 @@ application-area: [all] ## Description -`SecretStrSubstNo` is the secret-preserving counterpart of `StrSubstNo`. It inserts `SecretText` arguments into `%1`, `%2`, and similar placeholders and returns `SecretText` without materializing the result as plain text. It is the right tool for values such as a `Bearer %1` authorization header or a URI with an API key placeholder. +`SecretStrSubstNo` is the secret-preserving counterpart of `StrSubstNo`. It inserts `SecretText` arguments into `%1`, `%2`, and similar placeholders and returns `SecretText` without materializing the result as plain text. It is the right tool for values such as a `Token %1` authorization header or a URI with an API key placeholder. ## Best Practice diff --git a/microsoft/knowledge/security/secrettext-with-httpclient.bad.al b/microsoft/knowledge/security/secrettext-with-httpclient.bad.al index 86a8f43..6b11a4c 100644 --- a/microsoft/knowledge/security/secrettext-with-httpclient.bad.al +++ b/microsoft/knowledge/security/secrettext-with-httpclient.bad.al @@ -10,14 +10,14 @@ codeunit 50210 "Sec Sample SecretHttp Bad" HttpClient.Get(RequestUri, Response); end; - procedure CallApiWithBearer(BearerToken: Text) + procedure CallApiWithAccessToken(AccessToken: Text) var HttpClient: HttpClient; Response: HttpResponseMessage; Headers: HttpHeaders; begin Headers := HttpClient.DefaultRequestHeaders(); - Headers.Add('Authorization', StrSubstNo('Bearer %1', BearerToken)); + Headers.Add('Authorization', StrSubstNo('Token %1', AccessToken)); HttpClient.Get('https://api.example.com/data', Response); end; } diff --git a/microsoft/knowledge/security/secrettext-with-httpclient.good.al b/microsoft/knowledge/security/secrettext-with-httpclient.good.al index 199e2e6..e552512 100644 --- a/microsoft/knowledge/security/secrettext-with-httpclient.good.al +++ b/microsoft/knowledge/security/secrettext-with-httpclient.good.al @@ -13,7 +13,7 @@ codeunit 50209 "Sec Sample SecretHttp Good" HttpClient.Send(Request, Response); end; - procedure CallApiWithBearer(BearerToken: SecretText) + procedure CallApiWithAccessToken(AccessToken: SecretText) var HttpClient: HttpClient; Request: HttpRequestMessage; @@ -25,7 +25,7 @@ codeunit 50209 "Sec Sample SecretHttp Good" Request.Method := 'GET'; Request.SetRequestUri('https://api.example.com/data'); Request.GetHeaders(Headers); - AuthHeader := SecretStrSubstNo('Bearer %1', BearerToken); + AuthHeader := SecretStrSubstNo('Token %1', AccessToken); Headers.Add('Authorization', AuthHeader); if not Headers.ContainsSecret('Authorization') then Error(AuthorizationHeaderMissingErr);