fix(auth): isolate bounded OIDC cleanup

This commit is contained in:
2026-08-17 07:46:43 +02:00
parent bdabecbb63
commit 3e7bb11313
8 changed files with 456 additions and 177 deletions
+20 -13
View File
@@ -22,7 +22,8 @@ const (
maximumProtocolBytes = 64 * 1024
maximumSessionBytes = 16 * 1024
maximumOIDCStateBytes = 8 * 1024
maximumEntries = 256
defaultMaximumEntries = 256
maximumEntries = 512
)
var (
@@ -33,12 +34,13 @@ var (
)
type request struct {
Version int `json:"version"`
Operation string `json:"operation"`
Root string `json:"root"`
Directory string `json:"directory"`
Filename string `json:"filename,omitempty"`
ContentBase64 string `json:"contentBase64,omitempty"`
Version int `json:"version"`
Operation string `json:"operation"`
Root string `json:"root"`
Directory string `json:"directory"`
Filename string `json:"filename,omitempty"`
ContentBase64 string `json:"contentBase64,omitempty"`
MaximumEntries int `json:"maximumEntries,omitempty"`
}
type response struct {
@@ -137,7 +139,11 @@ func execute(input request) (response, error) {
}
return response{Version: protocolVersion, OK: true, Removed: removed}, nil
case "list":
entries, err := safeio.ListCanonicalPrivateDirectory(directory, maximumEntries)
limit := input.MaximumEntries
if limit == 0 {
limit = defaultMaximumEntries
}
entries, err := safeio.ListCanonicalPrivateDirectory(directory, limit)
if err != nil {
return response{}, errInvalid
}
@@ -175,17 +181,18 @@ func execute(input request) (response, error) {
func validOperationShape(input request) bool {
noContents := input.ContentBase64 == ""
noMaximumEntries := input.MaximumEntries == 0
switch input.Operation {
case "create", "replace":
return digestFilename.MatchString(input.Filename) || (input.Operation == "create" && input.Directory == "oidc" && oidcSlotFilename.MatchString(input.Filename))
return noMaximumEntries && (digestFilename.MatchString(input.Filename) || (input.Operation == "create" && input.Directory == "oidc" && oidcSlotFilename.MatchString(input.Filename)))
case "read":
return noContents && (digestFilename.MatchString(input.Filename) || (input.Directory == "oidc" && oidcSlotFilename.MatchString(input.Filename)))
return noContents && noMaximumEntries && (digestFilename.MatchString(input.Filename) || (input.Directory == "oidc" && oidcSlotFilename.MatchString(input.Filename)))
case "remove":
return noContents && (digestFilename.MatchString(input.Filename) || (input.Directory == "oidc" && (claimFilename.MatchString(input.Filename) || oidcSlotFilename.MatchString(input.Filename))))
return noContents && noMaximumEntries && (digestFilename.MatchString(input.Filename) || (input.Directory == "oidc" && (claimFilename.MatchString(input.Filename) || oidcSlotFilename.MatchString(input.Filename))))
case "list":
return input.Filename == "" && noContents
return input.Filename == "" && noContents && input.MaximumEntries >= 0 && input.MaximumEntries <= maximumEntries
case "claim-consume", "read-claim", "remove-claim":
return input.Directory == "oidc" && noContents && digestFilename.MatchString(input.Filename)
return input.Directory == "oidc" && noContents && noMaximumEntries && digestFilename.MatchString(input.Filename)
default:
return false
}