Sync from /srv/compose/unified-media-manager
This commit is contained in:
48
internal/cardigann/parser.go
Normal file
48
internal/cardigann/parser.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package cardigann
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// SearchQuery represents a search query to be templated into request URLs and inputs.
|
||||
type SearchQuery struct {
|
||||
Keywords string
|
||||
MediaType string
|
||||
}
|
||||
|
||||
// TemplateContext provides the data available to Cardigann templates.
|
||||
type TemplateContext struct {
|
||||
Query SearchQuery
|
||||
Config map[string]string
|
||||
Categories []string
|
||||
}
|
||||
|
||||
// ApplyTemplate processes a Go template string with the sandboxed Cardigann FuncMap.
|
||||
// The FuncMap contains ONLY "replace" to prevent SSRF or file access via templates.
|
||||
func ApplyTemplate(name, tpl string, ctx interface{}) (string, error) {
|
||||
tmpl, err := template.New(name).Funcs(sandboxedFuncMap()).Parse(tpl)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("parse template %q: %w", name, err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := tmpl.Execute(&buf, ctx); err != nil {
|
||||
return "", fmt.Errorf("execute template %q: %w", name, err)
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// sandboxedFuncMap returns a template FuncMap containing ONLY safe functions.
|
||||
// SECURITY: No file, network, environment, or exec access allowed.
|
||||
// Threat model T-10-02, T-10-06: FuncMap contains ONLY "replace".
|
||||
func sandboxedFuncMap() template.FuncMap {
|
||||
return template.FuncMap{
|
||||
"replace": func(old, new, src string) string {
|
||||
return strings.ReplaceAll(src, old, new)
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user