github.com/google/osv-scalibr@v0.4.1/detector/endoflife/linuxdistro/linuxdistro.go (about)

     1  // Copyright 2025 Google LLC
     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 linuxdistro implements a detector for End-of-Life Linux distributions
    16  package linuxdistro
    17  
    18  import (
    19  	"context"
    20  	"time"
    21  
    22  	"github.com/google/osv-scalibr/detector"
    23  	"github.com/google/osv-scalibr/extractor/filesystem/os/osrelease"
    24  	scalibrfs "github.com/google/osv-scalibr/fs"
    25  	"github.com/google/osv-scalibr/inventory"
    26  	"github.com/google/osv-scalibr/packageindex"
    27  	"github.com/google/osv-scalibr/plugin"
    28  )
    29  
    30  const (
    31  	// Name of the detector.
    32  	Name = "endoflife/linuxdistro"
    33  )
    34  
    35  var now = time.Now
    36  
    37  // Detector is a SCALIBR Detector for End-Of-Life linux distributions
    38  type Detector struct{}
    39  
    40  // New returns a detector.
    41  func New() detector.Detector {
    42  	return &Detector{}
    43  }
    44  
    45  // Name of the detector.
    46  func (Detector) Name() string { return Name }
    47  
    48  // Version of the detector.
    49  func (Detector) Version() int { return 0 }
    50  
    51  // Requirements of the detector.
    52  func (Detector) Requirements() *plugin.Capabilities {
    53  	return &plugin.Capabilities{OS: plugin.OSLinux}
    54  }
    55  
    56  // RequiredExtractors returns nothing (no deps).
    57  func (Detector) RequiredExtractors() []string { return []string{} }
    58  
    59  func eolFinding(target *inventory.GenericFindingTargetDetails) inventory.Finding {
    60  	title := "End-of-Life operating system"
    61  	description := "The system is running a Linux distribution that has reached end-of-life " +
    62  		"(EOL) and is no longer maintained by the vendor. This means it no longer " +
    63  		"receives security updates or patches."
    64  	recommendation := "Upgrade the operating system to a supported release or arrange " +
    65  		"an extended support with the vendor."
    66  	return inventory.Finding{GenericFindings: []*inventory.GenericFinding{{
    67  		Adv: &inventory.GenericFindingAdvisory{
    68  			ID: &inventory.AdvisoryID{
    69  				Publisher: "SCALIBR",
    70  				Reference: "linux-end-of-life",
    71  			},
    72  			Title:          title,
    73  			Description:    description,
    74  			Recommendation: recommendation,
    75  			Sev:            inventory.SeverityCritical,
    76  		},
    77  		Target: target,
    78  	}}}
    79  }
    80  
    81  var eolDetector = map[string]func(map[string]string, scalibrfs.FS) bool{
    82  	"fedora": fedoraEOL,
    83  	"ubuntu": ubuntuEOL,
    84  }
    85  
    86  // Scan checks for the presence of an end-of-life Linux OS on the host.
    87  func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) (inventory.Finding, error) {
    88  	osRelease, err := osrelease.GetOSRelease(scanRoot.FS)
    89  	if err != nil {
    90  		return inventory.Finding{}, err
    91  	}
    92  	distro, ok := osRelease["ID"]
    93  	if !ok {
    94  		return inventory.Finding{}, err
    95  	}
    96  	if detector, ok := eolDetector[distro]; ok {
    97  		if detector(osRelease, scanRoot.FS) {
    98  			target := &inventory.GenericFindingTargetDetails{Extra: "distro: " + distro}
    99  			return eolFinding(target), nil
   100  		}
   101  	}
   102  	return inventory.Finding{}, nil
   103  }
   104  
   105  // DetectedFinding returns generic vulnerability information about what is detected.
   106  func (d Detector) DetectedFinding() inventory.Finding {
   107  	return eolFinding(nil)
   108  }