All checks were successful
check / check (push) Successful in 2m54s
internal/handlers/source_management.go read the target destination
with r.FormValue, which falls back to the URL query string when the
field is absent from the body. So
POST /source/{id}/targets?url=https://hooks.slack.com/services/T/B/S
created a working target from a value carried on the request line,
where logs, proxies, Referer headers and error trackers record it.
That is the remaining ingress path of the credential-exposure class
the render, delivery-error and log-line paths were each closed for.
Every form read in these handlers is now r.PostFormValue, so no
query-string value can populate stored configuration or be taken as a
credential. The one deliberate query read, `page` on the authenticated
pagination links, is untouched: it uses r.URL.Query().Get already.
The access log no longer carries the query on any branch, so the log
half of the report is already mitigated; the Sentry half is not. The
SDK attaches the request to every captured event and copies
r.URL.RawQuery into Request.QueryString independently of the access
log, so a BeforeSend hook clears that field before an event leaves the
process. Scheme, host, path and method stay, which is what names the
failing route.
Second barrier, for the JSON path that does not exist yet: the fields
that hold a credential are tagged json:"-" so the first handler to
marshal a model cannot serialise one. Target.Config holds the
incoming-webhook URL, APIKey.Key is a bearer token, and Setting.Value
holds the session encryption key. delivery.TargetView remains the
masking barrier for the HTML path, which is unaffected.
41 lines
1.3 KiB
Go
41 lines
1.3 KiB
Go
package database
|
|
|
|
// TargetType represents the type of delivery target
|
|
type TargetType string
|
|
|
|
// Target type values.
|
|
const (
|
|
TargetTypeHTTP TargetType = "http"
|
|
TargetTypeDatabase TargetType = "database"
|
|
TargetTypeLog TargetType = "log"
|
|
TargetTypeSlack TargetType = "slack"
|
|
)
|
|
|
|
// Target represents a delivery target for a webhook
|
|
type Target struct {
|
|
BaseModel
|
|
|
|
WebhookID string `gorm:"type:uuid;not null" json:"webhookId"`
|
|
Name string `gorm:"not null" json:"name"`
|
|
Type TargetType `gorm:"not null" json:"type"`
|
|
Active bool `gorm:"default:true" json:"active"`
|
|
|
|
// Configuration fields (JSON stored based on type).
|
|
//
|
|
// json:"-" because the blob holds the target's credential — a
|
|
// Slack incoming-webhook URL, or an http destination whose path
|
|
// segments are the secret. delivery.TargetView is the masking
|
|
// barrier for the HTML path; this tag is the barrier for any
|
|
// handler that marshals the model itself.
|
|
Config string `gorm:"type:text" json:"-"` // JSON configuration
|
|
|
|
// For HTTP targets (max_retries=0 means fire-and-forget,
|
|
// >0 enables retries with backoff)
|
|
MaxRetries int `json:"maxRetries,omitempty"`
|
|
MaxQueueSize int `json:"maxQueueSize,omitempty"`
|
|
|
|
// Relations
|
|
Webhook Webhook `json:"webhook,omitzero"`
|
|
Deliveries []Delivery `json:"deliveries,omitempty"`
|
|
}
|