-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementation of Wordpress plugins packages Extractor #363
Open
Octaviusss
wants to merge
10
commits into
google:main
Choose a base branch
from
mindedsecurity:extractor_wordpress
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+461
−2
Open
Changes from 9 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
23f2f79
Implementation of Wordpress plugins extractor
Octaviusss b8d74cd
Merge branch 'google:main' into extractor_wordpress
Octaviusss d465d05
Merge branch 'google:main' into extractor_wordpress
Octaviusss 9f6354e
Fix issues
Octaviusss 1b9f760
Merge branch 'main' into extractor_wordpress
Octaviusss 7345ddb
Merge branch 'main' into extractor_wordpress
Octaviusss b3f80fa
fix tests
Octaviusss 2408e35
Merge branch 'main' into extractor_wordpress
Octaviusss 981e839
making lint happy
Octaviusss d97e32b
add fixes
Octaviusss File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
189 changes: 189 additions & 0 deletions
189
extractor/filesystem/language/wordpress/plugins/plugins.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
// Copyright 2024 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
// Package wordpress extracts packages from installed plugins. | ||
package plugins | ||
|
||
import ( | ||
"bufio" | ||
"context" | ||
"fmt" | ||
"io" | ||
"strings" | ||
|
||
"github.com/google/osv-scalibr/extractor" | ||
"github.com/google/osv-scalibr/extractor/filesystem" | ||
"github.com/google/osv-scalibr/extractor/filesystem/internal/units" | ||
"github.com/google/osv-scalibr/plugin" | ||
"github.com/google/osv-scalibr/purl" | ||
"github.com/google/osv-scalibr/stats" | ||
) | ||
|
||
const ( | ||
// Name is the unique name of this extractor. | ||
Name = "wordpress/plugins" | ||
) | ||
|
||
// Config is the configuration for the Wordpress extractor. | ||
type Config struct { | ||
// Stats is a stats collector for reporting metrics. | ||
Stats stats.Collector | ||
// MaxFileSizeBytes is the maximum file size this extractor will unmarshal. If | ||
// `FileRequired` gets a bigger file, it will return false, | ||
MaxFileSizeBytes int64 | ||
} | ||
|
||
// DefaultConfig returns the default configuration for the Wordpress extractor. | ||
func DefaultConfig() Config { | ||
return Config{ | ||
Stats: nil, | ||
MaxFileSizeBytes: 10 * units.MiB, | ||
} | ||
} | ||
|
||
// Extractor structure for plugins files. | ||
type Extractor struct { | ||
stats stats.Collector | ||
maxFileSizeBytes int64 | ||
} | ||
|
||
// New returns a Wordpress extractor. | ||
// | ||
// For most use cases, initialize with: | ||
// ``` | ||
// e := New(DefaultConfig()) | ||
// ``` | ||
func New(cfg Config) *Extractor { | ||
return &Extractor{ | ||
stats: cfg.Stats, | ||
maxFileSizeBytes: cfg.MaxFileSizeBytes, | ||
} | ||
} | ||
|
||
// Config returns the configuration of the extractor. | ||
func (e Extractor) Config() Config { | ||
return Config{ | ||
Stats: e.stats, | ||
MaxFileSizeBytes: e.maxFileSizeBytes, | ||
} | ||
} | ||
|
||
// Name of the extractor. | ||
func (e Extractor) Name() string { return Name } | ||
|
||
// Version of the extractor. | ||
func (e Extractor) Version() int { return 0 } | ||
|
||
// Requirements of the extractor. | ||
func (e Extractor) Requirements() *plugin.Capabilities { return &plugin.Capabilities{} } | ||
|
||
// FileRequired returns true if the specified file matches the /wp-content/plugins/ pattern. | ||
func (e Extractor) FileRequired(api filesystem.FileAPI) bool { | ||
path := api.Path() | ||
if !strings.Contains(path, "wp-content/plugins/") || !strings.HasSuffix(path, ".php") { | ||
Octaviusss marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return false | ||
} | ||
|
||
fileinfo, err := api.Stat() | ||
if err != nil { | ||
return false | ||
} | ||
|
||
if e.maxFileSizeBytes > 0 && fileinfo.Size() > e.maxFileSizeBytes { | ||
e.reportFileRequired(path, fileinfo.Size(), stats.FileRequiredResultSizeLimitExceeded) | ||
return false | ||
} | ||
|
||
e.reportFileRequired(path, fileinfo.Size(), stats.FileRequiredResultOK) | ||
return true | ||
} | ||
|
||
func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result stats.FileRequiredResult) { | ||
if e.stats == nil { | ||
return | ||
} | ||
e.stats.AfterFileRequired(e.Name(), &stats.FileRequiredStats{ | ||
Path: path, | ||
Result: result, | ||
FileSizeBytes: fileSizeBytes, | ||
}) | ||
} | ||
|
||
// Extract parses the PHP file to extract Wordpress package. | ||
func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { | ||
pkgs, err := parsePHPFile(input.Reader) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var inventories []*extractor.Inventory | ||
for _, pkg := range pkgs { | ||
Octaviusss marked this conversation as resolved.
Show resolved
Hide resolved
|
||
inventories = append(inventories, &extractor.Inventory{ | ||
Name: pkg.Name, | ||
Version: pkg.Version, | ||
Locations: []string{input.Path}, | ||
}) | ||
} | ||
|
||
return inventories, nil | ||
} | ||
|
||
type Package struct { | ||
Name string | ||
Version string | ||
} | ||
|
||
func parsePHPFile(r io.Reader) ([]Package, error) { | ||
Octaviusss marked this conversation as resolved.
Show resolved
Hide resolved
|
||
scanner := bufio.NewScanner(r) | ||
var pkgs []Package | ||
|
||
var name, version string | ||
for scanner.Scan() { | ||
line := scanner.Text() | ||
|
||
if strings.Contains(line, "Plugin Name:") { | ||
name = strings.TrimSpace(strings.Split(line, "Plugin Name:")[1]) | ||
} | ||
|
||
if strings.Contains(line, "Version:") { | ||
version = strings.TrimSpace(strings.Split(line, ":")[1]) | ||
} | ||
|
||
if name != "" && version != "" { | ||
pkgs = append(pkgs, Package{Name: name, Version: version}) | ||
break | ||
} | ||
} | ||
|
||
if err := scanner.Err(); err != nil { | ||
return nil, fmt.Errorf("failed to read PHP file: %w", err) | ||
} | ||
|
||
return pkgs, nil | ||
} | ||
|
||
// ToPURL converts an inventory created by this extractor into a PURL. | ||
func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { | ||
return &purl.PackageURL{ | ||
Type: purl.TypeWordpress, | ||
Name: i.Name, | ||
Version: i.Version, | ||
} | ||
} | ||
|
||
// Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. | ||
func (e Extractor) Ecosystem(_ *extractor.Inventory) string { | ||
// wordpress ecosystem does not exist in OSV | ||
return "" | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is a sync issue, but the only change should be the lines about wordpress plugins