Skip to content

Comments

Improve Quick fix#1702

Open
5byuri wants to merge 45 commits intomainfrom
Improve-Quick-Fix
Open

Improve Quick fix#1702
5byuri wants to merge 45 commits intomainfrom
Improve-Quick-Fix

Conversation

@5byuri
Copy link
Member

@5byuri 5byuri commented Feb 13, 2026

No description provided.

Copilot AI review requested due to automatic review settings February 13, 2026 15:28
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a prototype “quick fix” workflow under cmd/devguard-cli/test/ to fetch package metadata from registries (npm/crates) and attempt to validate whether updating a dependency chain results in a vulnerable package version being at/above a fixed version.

Changes:

  • Add npm registry response type definitions for JSON unmarshalling.
  • Add registry helper functions (npm/crates) and a quickfix CLI that walks a dependency chain.
  • Add semver parsing/recommendation logic to select newer versions within the same major band.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 13 comments.

File Description
cmd/devguard-cli/test/types.go Introduces structs for npm registry JSON responses.
cmd/devguard-cli/test/quickfix.go Implements the dependency-chain “quick fix” logic and a main() driver.
cmd/devguard-cli/test/package_manager_functions.go Adds registry request helpers for npm/crates and a version existence check.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 23 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 19 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 125 to 141
func parsePurl(purl string) (string, string, error) {
// Format: pkg:npm/package-name@version or pkg:npm/@scoped/package@version
// Note: version can be empty string to indicate "all versions" (see RegistryRequest)
input, err := packageurl.FromString(purl)
if err != nil {
return "", "", fmt.Errorf("invalid purl format: %w", err)
}

pkgName := input.Name
if input.Namespace != "" {
pkgName = input.Namespace + "/" + input.Name
}

version := input.Version

return pkgName, version, nil
}
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parsePurl function only returns the package name and version, but doesn't return the package type (npm, cargo, etc.) which is available in the purl. This type information is needed to properly determine which package manager/registry to query. The function should return a third value (input.Type) or the entire PackageURL struct so callers can determine the correct package manager.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (10)

cmd/devguard-cli/test/quickfix.go:243

  • The comment block above resolveBestVersion says OR expressions are "not implemented yet", but the function now implements "||" handling below. Please update/remove the stale comment to avoid misleading future readers.
	// Handle OR expressions - not implemented yet, return error
	// if strings.Contains(versionSpec, "||") {
	// 	return "", fmt.Errorf("OR expressions (||) not yet supported: %s", versionSpec)
	// }

cmd/devguard-cli/test/quickfix.go:297

  • There are remaining fmt.Println debug statements (printing parts) inside resolveBestVersion’s OR-handling loop. These will pollute stdout and make the function unsuitable for library use/tests. Remove the prints or replace them with structured debug logging behind a flag.
				parts := strings.Split(orBaseVersion, ".")
				fmt.Println(parts)
				// 14.0 is not getting caught by semver.isValid

cmd/devguard-cli/test/quickfix.go:121

  • parseVersion writes an "ERROR" line to stderr on parse failure. This helper is used in sorting/comparisons and will create noisy output in tests and CLI runs; it also silently converts parse failures to 0.0.0. Prefer returning an error to the caller, or (since callers already semver-validate) remove the stderr logging and handle invalid input deterministically.
	if _, err := fmt.Sscanf(cleanVersion, "%d.%d.%d", &result[0], &result[1], &result[2]); err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: Failed to parse version %q: %v (this indicates a validation bypass)\n", version, err)
		return [3]int{0, 0, 0}
	}

cmd/devguard-cli/test/quickfix.go:170

  • splitOrExpression has a fmt.Println(result) side effect. This will spam stdout during tests/usage and makes the helper non-deterministic. Remove the print or gate it behind an explicit debug logger/flag.
	fmt.Println(result)
	return result

cmd/devguard-cli/test/quickfix.go:457

  • getVersion supports both npm and crates, but fetchPackageMetadata always decodes responses into NPMResponse. If pkgManager is ever "crates", JSON decoding will be wrong. Either restrict this helper to npm/node explicitly, or introduce per-registry response types so decoding matches the selected registry.
	var npmResp NPMResponse
	if err := json.NewDecoder(resp.Body).Decode(&npmResp); err != nil {
		return nil, fmt.Errorf("error decoding JSON for %s@%s: %w", dep, version, err)

cmd/devguard-cli/test/quickfix.go:467

  • This directory defines a package main with its own main() entrypoint under cmd/devguard-cli/test. If CI/dev scripts ever build/install ./cmd/... this will produce an extra binary (named "test") and ship hard-coded network behavior. If this is only a local playground, consider moving it out of cmd/ or adding a build tag to exclude it from normal builds.
func main() {
	purls := []string{
		"pkg:npm/@sentry/nextjs@9.38.0",
		/*
			nextjs@9.39.0 ---> Ist abhängig von react@6.28.0

cmd/devguard-cli/test/types.go:94

  • Type name "Signatures" is plural but represents a single signature object. For Go naming clarity, prefer a singular type name (e.g. Signature) and keep the slice field plural (e.g. Signatures []Signature).
type Signatures struct {
	Sig   string `json:"sig"`
	KeyID string `json:"keyid"`
}

cmd/devguard-cli/test/quickfix_test.go:5

  • The new test file uses an Apache-2.0 license header, while other files under cmd/devguard-cli use the AGPL header (e.g. cmd/devguard-cli/commands/root.go). If this file isn’t copied from an Apache-licensed upstream source, update the header to match the rest of the devguard-cli code to avoid license inconsistencies.
// Copyright 2026 larshermges
//
// 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

cmd/devguard-cli/test/package_manager_functions.go:41

  • The comment says "remove quotes if present" but the code trims '/' characters from the version. Either adjust the comment to match what’s happening or trim the actual characters you intend to normalize (and consider validating the version path segment).
	normalizedVersion := strings.Trim(pkg.Version, "/") // remove quotes if present

	if pkg.Version != "" {

cmd/devguard-cli/test/quickfix.go:470

  • There’s an inline multi-line comment in German inside main(). This makes the codebase harder to maintain for non-German speakers and reads like a scratch note. Prefer converting this to an English comment with actionable context, or move the reasoning to an issue/PR description.
		/*
			nextjs@9.39.0 ---> Ist abhängig von react@6.28.0

			packages[i+1].version = 6.28.0
			1. Erneut getRecommendedVersions für react@6.28.0??? Aber ist doch fixed von nextjs

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (8)

cmd/devguard-cli/test/package_manager_functions.go:40

  • strings.Trim(pkg.Version, "/") does not "remove quotes" (it removes / characters). If the intent is to normalize user input, use a quote/whitespace trim that matches the comment (or update the comment so it reflects the actual behavior).
	normalizedVersion := strings.Trim(pkg.Version, "/") // remove quotes if present

cmd/devguard-cli/test/package_manager_functions.go:3

  • New file header deviates from the standard header used elsewhere in cmd/devguard-cli (e.g., // Copyright (C) 2026 l3montree GmbH). To keep licensing/copyright notices consistent, align this header with the existing convention.
// Copyright 2026 lars hermges @ l3montree GmbH

// This program is free software: you can redistribute it and/or modify

cmd/devguard-cli/test/quickfix.go:258

  • This comment says OR expressions are "not implemented yet", but the function now implements || handling below. This is misleading for future readers; update or remove the comment to match the current behavior.
	// Handle OR expressions - not implemented yet, return error
	// if strings.Contains(versionSpec, "||") {
	// 	return "", fmt.Errorf("OR expressions (||) not yet supported: %s", versionSpec)
	// }

cmd/devguard-cli/test/quickfix.go:188

  • >= and > are implemented as "same major version" comparisons. That differs from typical semver range semantics (where >=1.2.3 can match 2.0.0), and the inline comments don’t mention this restriction. Either document this as an intentional "same-major" policy (including in the rangeType docs), or adjust the logic to follow standard operator semantics.
	case ">=":
		// Greater than or equal: same major version, >= base
		return versionParts[0] == baseParts[0] && semver.Compare("v"+version, "v"+baseVersion) >= 0

	case ">":
		// Greater than: same major version, > base
		return versionParts[0] == baseParts[0] && semver.Compare("v"+version, "v"+baseVersion) > 0

.vscode/launch.json:53

  • The new launch configuration block is indented differently from the surrounding entries and has an empty multiline args array, which makes the JSONC harder to read/maintain. Consider matching the existing formatting (indentation and "args": [] style) used by the other configurations in this file.
    {
        "name": "Launch DepTreeWalk",
        "type": "go",
        "request": "launch",
        "cwd": "${workspaceRoot}",
        "mode": "auto",
        "program": "${workspaceRoot}/cmd/devguard-cli/test",
        "args": [
        ],
    },

cmd/devguard-cli/test/package_manager_functions.go:69

  • Similar to the NPM call, pkg.Dependency/pkg.Version are concatenated into the URL path without escaping. While crate names are usually simple, this still permits malformed input (extra slashes, ..) to change the requested path. Consider URL-escaping these path segments before building the request URL.
	if pkg.Version != "" {
		req, err = httpClient.Get("https://crates.io/api/v1/crates/" + pkg.Dependency + "/" + pkg.Version)
	} else {
		req, err = httpClient.Get("https://crates.io/api/v1/crates/" + pkg.Dependency)
	}

cmd/devguard-cli/test/quickfix.go:3

  • The file header differs from the standard AGPL header format used in other cmd/devguard-cli Go files (e.g., the commands package). Aligning the copyright line/format avoids inconsistency in licensing notices across the repo.
// Copyright 2026 lars hermges @ l3montree GmbH

// This program is free software: you can redistribute it and/or modify

cmd/devguard-cli/test/types.go:95

  • The type name Signatures is plural, but it represents a single signature, and it results in the awkward field Signatures []Signatures. Renaming the struct to Signature (and keeping the field name Signatures) would make the API clearer.
type Dist struct {
	Shasum     string       `json:"shasum"`
	Tarball    string       `json:"tarball"`
	Integrity  string       `json:"integrity"`
	Signatures []Signatures `json:"signatures"`
}

type Repository struct {
	URL  string `json:"url"`
	Type string `json:"type"`
}

type Signatures struct {
	Sig   string `json:"sig"`
	KeyID string `json:"keyid"`
}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant