gopkg.in/alecthomas/gometalinter.v3@v3.0.0/_linters/src/github.com/securego/gosec/rules/fileperms.go (about)

     1  // (c) Copyright 2016 Hewlett Packard Enterprise Development LP
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package rules
    16  
    17  import (
    18  	"fmt"
    19  	"go/ast"
    20  	"strconv"
    21  
    22  	"github.com/securego/gosec"
    23  )
    24  
    25  type filePermissions struct {
    26  	gosec.MetaData
    27  	mode  int64
    28  	pkg   string
    29  	calls []string
    30  }
    31  
    32  func (r *filePermissions) ID() string {
    33  	return r.MetaData.ID
    34  }
    35  
    36  func getConfiguredMode(conf map[string]interface{}, configKey string, defaultMode int64) int64 {
    37  	var mode = defaultMode
    38  	if value, ok := conf[configKey]; ok {
    39  		switch value.(type) {
    40  		case int64:
    41  			mode = value.(int64)
    42  		case string:
    43  			if m, e := strconv.ParseInt(value.(string), 0, 64); e != nil {
    44  				mode = defaultMode
    45  			} else {
    46  				mode = m
    47  			}
    48  		}
    49  	}
    50  	return mode
    51  }
    52  
    53  func (r *filePermissions) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
    54  	if callexpr, matched := gosec.MatchCallByPackage(n, c, r.pkg, r.calls...); matched {
    55  		modeArg := callexpr.Args[len(callexpr.Args)-1]
    56  		if mode, err := gosec.GetInt(modeArg); err == nil && mode > r.mode {
    57  			return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
    58  		}
    59  	}
    60  	return nil, nil
    61  }
    62  
    63  // NewFilePerms creates a rule to detect file creation with a more permissive than configured
    64  // permission mask.
    65  func NewFilePerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
    66  	mode := getConfiguredMode(conf, "G302", 0600)
    67  	return &filePermissions{
    68  		mode:  mode,
    69  		pkg:   "os",
    70  		calls: []string{"OpenFile", "Chmod"},
    71  		MetaData: gosec.MetaData{
    72  			ID:         id,
    73  			Severity:   gosec.Medium,
    74  			Confidence: gosec.High,
    75  			What:       fmt.Sprintf("Expect file permissions to be %#o or less", mode),
    76  		},
    77  	}, []ast.Node{(*ast.CallExpr)(nil)}
    78  }
    79  
    80  // NewMkdirPerms creates a rule to detect directory creation with more permissive than
    81  // configured permission mask.
    82  func NewMkdirPerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
    83  	mode := getConfiguredMode(conf, "G301", 0750)
    84  	return &filePermissions{
    85  		mode:  mode,
    86  		pkg:   "os",
    87  		calls: []string{"Mkdir", "MkdirAll"},
    88  		MetaData: gosec.MetaData{
    89  			ID:         id,
    90  			Severity:   gosec.Medium,
    91  			Confidence: gosec.High,
    92  			What:       fmt.Sprintf("Expect directory permissions to be %#o or less", mode),
    93  		},
    94  	}, []ast.Node{(*ast.CallExpr)(nil)}
    95  }