Skip to content
This repository has been archived by the owner on Mar 27, 2023. It is now read-only.

Commit

Permalink
Last changes from jan 9th meeting (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
puerco authored Jan 10, 2023
2 parents ae825ab + 102a882 commit 249b144
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 31 deletions.
44 changes: 17 additions & 27 deletions internal/cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ type createOptions struct {

// Validates the options in context with arguments
func (o *createOptions) Validate(args []string) error {
if o.Status != string(vex.StatusAffected) && o.ActionStatement == vex.NoActionStatementMsg {
o.ActionStatement = ""
}
if len(args) == 0 && len(o.Products) == 0 {
return errors.New("a required product id is required to generate a valid VEX statement")
}
Expand All @@ -43,33 +46,6 @@ func (o *createOptions) Validate(args []string) error {
return errors.New("status can only be specified once")
}

statusString := o.Status
if statusString == "" {
if len(args) < 3 {
return fmt.Errorf("a valid status is required to generate a valid VEX statement")
}
statusString = args[2]
}
status := vex.Status(statusString)
if !status.Valid() {
return fmt.Errorf(
"invalid VEX impact status '%s', valid status are: %s",
status, strings.Join(vex.Statuses(), ", "),
)
}

if status == vex.StatusNotAffected {
if o.Justification == "" {
return fmt.Errorf("an '%s' statement requires a valid justification: [%s]", vex.StatusAffected, strings.Join(vex.Justifications(), ", "))
}

if !vex.Justification(o.Justification).Valid() {
return fmt.Errorf("%s is not a valid VEX justification, valid justifications: %s", vex.StatusAffected, strings.Join(vex.Justifications(), ", "))
}
} else if o.Justification != "" {
return fmt.Errorf("a %s impact status must not have a justification", status)
}

return nil
}

Expand Down Expand Up @@ -145,7 +121,13 @@ Examples:
StatusNotes: opts.StatusNotes,
Justification: vex.Justification(opts.Justification),
ImpactStatement: opts.ImpactStatement,
ActionStatement: opts.ActionStatement,
}

if err := statement.Validate(); err != nil {
return fmt.Errorf("invalid statement: %w", err)
}

newDoc.Statements = append(newDoc.Statements, statement)
if _, err := newDoc.GenerateCanonicalID(); err != nil {
return fmt.Errorf("generating document id: %w", err)
Expand Down Expand Up @@ -233,6 +215,14 @@ Examples:
fmt.Sprintf("justification for not_affected status, see '%s show justifications' for list", appname),
)

createCmd.PersistentFlags().StringVarP(
&opts.ActionStatement,
"action-statement",
"a",
vex.NoActionStatementMsg,
"action statement for affected status",
)

createCmd.PersistentFlags().StringVar(
&opts.outFilePath,
"file",
Expand Down
1 change: 1 addition & 0 deletions internal/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ type vexStatementOptions struct {
Justification string
ImpactStatement string
Vulnerability string
ActionStatement string
Products []string
Subcomponents []string
}
Expand Down
14 changes: 10 additions & 4 deletions pkg/vex/statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ type Statement struct {
// that contains a description why the vulnerability cannot be exploited.
ImpactStatement string `json:"impact_statement,omitempty"`

// For "affected" status, a VEX statement MAY include an ActionStatement that
// For "affected" status, a VEX statement MUST include an ActionStatement that
// SHOULD describe actions to remediate or mitigate [vul_id].
ActionStatement string `json:"action_statement,omitempty"`
ActionStatementTimestamp *time.Time `json:"action_statement_timestamp,omitempty"`
Expand All @@ -69,11 +69,12 @@ func (stmt Statement) Validate() error { //nolint:gocritic // turning off for ru
case StatusNotAffected:
// require a justification
j := stmt.Justification
if j == "" {
return fmt.Errorf("justification missing, it's required when using status %q", s)
is := stmt.ImpactStatement
if j == "" && is == "" {
return fmt.Errorf("either justification or impact statement must be defined when using status %q", s)
}

if !j.Valid() {
if j != "" && !j.Valid() {
return fmt.Errorf("invalid justification value %q, must be one of [%s]", j, strings.Join(Justifications(), ", "))
}

Expand All @@ -92,6 +93,11 @@ func (stmt Statement) Validate() error { //nolint:gocritic // turning off for ru
return fmt.Errorf("impact statement should not be set when using status %q (was set to %q)", s, v)
}

// action statement is now required
if v := stmt.ActionStatement; v == "" {
return fmt.Errorf("action statement must be set when using status %q", s)
}

case StatusUnderInvestigation:
// irrelevant fields should not be set
if v := stmt.Justification; v != "" {
Expand Down
3 changes: 3 additions & 0 deletions pkg/vex/vex.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ const (

// PublicNamespace is the public openvex namespace for common @ids
PublicNamespace = "https://openvex.dev/docs"

// NoActionStatementMsg is the action statement that informs that there is no action statement :/
NoActionStatementMsg = "No action statement provided"
)

// The VEX type represents a VEX document and all of its contained information.
Expand Down

0 comments on commit 249b144

Please sign in to comment.