MCPcopy Create free account
hub / github.com/github/gh-aw / validateExpressionSafety

Function validateExpressionSafety

pkg/workflow/expression_safety_validation.go:35–136  ·  view source on GitHub ↗

validateExpressionSafety checks that all GitHub Actions expressions in the markdown content are in the allowed list and returns an error if any unauthorized expressions are found

(markdownContent string)

Source from the content-addressed store, hash-verified

33// validateExpressionSafety checks that all GitHub Actions expressions in the markdown content
34// are in the allowed list and returns an error if any unauthorized expressions are found
35func validateExpressionSafety(markdownContent string) error {
36 expressionValidationLog.Print("Validating expression safety in markdown content")
37
38 matches := ExpressionPatternDotAll.FindAllStringSubmatch(markdownContent, -1)
39 expressionValidationLog.Printf("Found %d expressions to validate", len(matches))
40
41 var unauthorizedExpressions []string
42
43 for _, match := range matches {
44 if len(match) < 2 {
45 continue
46 }
47
48 // Extract the expression content (everything between ${{ and }})
49 expression := strings.TrimSpace(match[1])
50
51 // Reject expressions that span multiple lines (contain newlines)
52 if strings.Contains(match[1], "\n") {
53 unauthorizedExpressions = append(unauthorizedExpressions, expression)
54 continue
55 }
56
57 // Try to parse the expression using the parser
58 parsed, parseErr := ParseExpression(expression)
59 if parseErr == nil {
60 // If we can parse it, validate each literal expression in the tree
61 validationErr := VisitExpressionTree(parsed, func(expr *ExpressionNode) error {
62 return validateSingleExpression(expr.Expression, ExpressionValidationOptions{
63 NeedsStepsRe: NeedsStepsPattern,
64 InputsRe: InputsPattern,
65 WorkflowCallInputsRe: WorkflowCallInputsPattern,
66 AwInputsRe: AWInputsPattern,
67 AwImportInputsRe: AWImportInputsPattern,
68 EnvRe: EnvPattern,
69 UnauthorizedExpressions: &unauthorizedExpressions,
70 })
71 })
72 if validationErr != nil {
73 return validationErr
74 }
75 } else {
76 // If parsing fails, fall back to validating the whole expression as a literal
77 err := validateSingleExpression(expression, ExpressionValidationOptions{
78 NeedsStepsRe: NeedsStepsPattern,
79 InputsRe: InputsPattern,
80 WorkflowCallInputsRe: WorkflowCallInputsPattern,
81 AwInputsRe: AWInputsPattern,
82 AwImportInputsRe: AWImportInputsPattern,
83 EnvRe: EnvPattern,
84 UnauthorizedExpressions: &unauthorizedExpressions,
85 })
86 if err != nil {
87 return err
88 }
89 }
90 }
91
92 if len(unauthorizedExpressions) > 0 {

Calls 8

FindClosestMatchesFunction · 0.92
ParseExpressionFunction · 0.85
VisitExpressionTreeFunction · 0.85
validateSingleExpressionFunction · 0.85
PrintMethod · 0.80
NewValidationErrorFunction · 0.70
PrintfMethod · 0.45
StringMethod · 0.45