All checks were successful
check / check (push) Successful in 4m7s
The source detail page rendered each target's stored config blob verbatim. For a slack target that blob contains the incoming webhook URL, which is a bearer credential: anyone holding it can post to the channel indefinitely, and it cannot be scoped or revoked per holder. Rendering it put the credential into browser history, screenshots and any support screen share. Targets are now projected to a display-safe TargetView that has no raw config field at all, so no template can render the blob. Each type contributes named fields instead: slack shows only a masked webhook URL, http shows its destination, timeout, header count and retry settings, and database shows its archive expiry. Header values are not shown because they routinely carry authorization tokens. Masking is a method on the config type, SlackTargetConfig.MaskedWebhookURL, so it is unit-testable and cannot be bypassed from a template. It reduces the URL to scheme and host, eliding the path, query and any userinfo: the field accepts an arbitrary URL, so no path segment can be assumed non-secret. Any config that is empty, of an unknown type, or fails to parse renders a neutral placeholder — there is no fallback to the stored string on any path. The stored config format and the delivery path are unchanged.
4.2 KiB
4.2 KiB