diff --git a/docs/syntax.md b/docs/syntax.md index 7d07e53..5cd9df0 100644 --- a/docs/syntax.md +++ b/docs/syntax.md @@ -21,12 +21,14 @@ require ( example.com/mod201 v1.2.3 // indirect ) -// policy cannot be specified here because the parser ignores -// the comment lines here +//gomodjail:unconfined require ( + example.com/mod300 v1.2.3 + example.com/mod301 v1.2.3 // gomodjail:confined + example.com/mod302 v1.2.3 ) ``` -This makes the following modules confined: `mod100`, `mod102`, and `mod201`. +This makes the following modules confined: `mod100`, `mod102`, `mod201`, and `mod301`. The version numbers are ignored. diff --git a/pkg/profile/fromgomod/fromgomod.go b/pkg/profile/fromgomod/fromgomod.go index 359a05e..4c5de65 100644 --- a/pkg/profile/fromgomod/fromgomod.go +++ b/pkg/profile/fromgomod/fromgomod.go @@ -40,6 +40,19 @@ func FromGoMod(mod *modfile.File, prof *profile.Profile) error { for _, f := range mod.Require { if syn := f.Syntax; syn != nil { pol := currentDefaultPolicy + if syn.InBlock { + // TODO: cache line blocks + if lineBlock := findLineBlock(mod.Syntax.Stmt, syn); lineBlock != nil { + lineBlockPol, err := policyFromLineBlock(lineBlock) + if err != nil { + err = fmt.Errorf("failed to parse line block %+v: %w", lineBlock, err) + return err + } + if lineBlockPol != "" { + pol = lineBlockPol + } + } + } for _, c := range append(syn.Before, syn.Suffix...) { if tok := c.Token; tok != "" { polFromComment, err := policyFromComment(tok) @@ -86,3 +99,33 @@ func policyFromComment(token string) (string, error) { } return "", nil } + +func findLineBlock(exprs []modfile.Expr, line modfile.Expr) *modfile.LineBlock { + start, end := line.Span() + for _, expr := range exprs { + lb, ok := expr.(*modfile.LineBlock) + if !ok { + continue + } + lbStart, lbEnd := lb.Span() + if start.Line >= lbStart.Line && end.Line <= lbEnd.Line { + return lb + } + } + return nil +} + +func policyFromLineBlock(lb *modfile.LineBlock) (string, error) { + for _, c := range append(lb.Before, lb.Suffix...) { + if tok := c.Token; tok != "" { + pol, err := policyFromComment(tok) + if err != nil { + return "", err + } + if pol != "" { + return pol, nil + } + } + } + return "", nil +} diff --git a/pkg/profile/fromgomod/fromgomod_test.go b/pkg/profile/fromgomod/fromgomod_test.go index e1632f2..606af7e 100644 --- a/pkg/profile/fromgomod/fromgomod_test.go +++ b/pkg/profile/fromgomod/fromgomod_test.go @@ -74,9 +74,18 @@ require ( example.com/mod202 v1.2.3 // indirect ) -// policy cannot be specified here because the parser ignores -// the comment lines here +//gomodjail:unconfined require ( + example.com/mod300 v1.2.3 + example.com/mod301 v1.2.3 // gomodjail:confined + example.com/mod302 v1.2.3 +) + +// gomodjail:confined +require ( + example.com/mod400 v1.2.3 // indirect + example.com/mod401 v1.2.3 // indirect // gomodjail:unconfined + example.com/mod402 v1.2.3 // indirect ) `, expected: map[string]string{ @@ -84,6 +93,23 @@ require ( "example.com/mod102": "confined", "example.com/mod201": "confined", "example.com/mod202": "confined", + "example.com/mod301": "confined", + "example.com/mod400": "confined", + "example.com/mod402": "confined", + }, + }, + + { + name: "blockless", + goMod: ` +module example.com/foo + +go 1.23 + +require example.com/mod v1.2.3 // gomodjail:confined +`, + expected: map[string]string{ + "example.com/mod": "confined", }, }, }