Skip to content
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

CycloneDX Dependencies Relationships Inverted #1815

Closed
shanealv opened this issue May 15, 2023 · 0 comments · Fixed by #1816
Closed

CycloneDX Dependencies Relationships Inverted #1815

shanealv opened this issue May 15, 2023 · 0 comments · Fixed by #1816
Labels
bug Something isn't working

Comments

@shanealv
Copy link
Contributor

What happened:

(previously reported in anchore/grype#1294)

When running syft convert on a CycloneDX SBOM with a "dependencies" section and outputting back to a CycloneDX, the dependency relationships appear to be inverted.

So this SBOM:

cat bom.json
{
  "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json",
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "version": 1,
  "components": [
    {
      "bom-ref": "pkg:golang/github.com/inconshreveable/mousetrap@v1.1.0?type=module",
      "type": "library",
      "name": "github.com/inconshreveable/mousetrap",
      "version": "v1.1.0",
      "purl": "pkg:golang/github.com/inconshreveable/mousetrap@v1.1.0?type=module\u0026goos=linux\u0026goarch=amd64"
    },
    {
      "bom-ref": "pkg:golang/github.com/spf13/cobra@v1.7.0?type=module",
      "type": "library",
      "name": "github.com/spf13/cobra",
      "version": "v1.7.0",
      "purl": "pkg:golang/github.com/spf13/cobra@v1.7.0?type=module\u0026goos=linux\u0026goarch=amd64"
    },
    {
      "bom-ref": "pkg:golang/github.com/spf13/pflag@v1.0.5?type=module",
      "type": "library",
      "name": "github.com/spf13/pflag",
      "version": "v1.0.5",
      "purl": "pkg:golang/github.com/spf13/pflag@v1.0.5?type=module\u0026goos=linux\u0026goarch=amd64"
    }
  ],
  "dependencies": [
    {
      "ref": "pkg:golang/github.com/inconshreveable/mousetrap@v1.1.0?type=module"
    },
    {
      "ref": "pkg:golang/github.com/spf13/cobra@v1.7.0?type=module",
      "dependsOn": [
        "pkg:golang/github.com/inconshreveable/mousetrap@v1.1.0?type=module",
        "pkg:golang/github.com/spf13/pflag@v1.0.5?type=module"
      ]
    },
    {
      "ref": "pkg:golang/github.com/spf13/pflag@v1.0.5?type=module"
    }
  ]
}

Became this:

syft convert bom.json -o cyclonedx-json
{
  "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json",
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "serialNumber": "urn:uuid:606f5b8f-c41f-4c13-afa5-85f506733c06",
  "version": 1,
  "metadata": {
    "timestamp": "2023-05-14T17:27:42-06:00",
    "tools": [
      {
        "vendor": "anchore",
        "name": "syft"
      }
    ]
  },
  "components": [
    {
      "bom-ref": "pkg:golang/github.com/inconshreveable/mousetrap@v1.1.0?type=module&goos=linux&goarch=amd64&package-id=4ef988ea2ded80a1",
      "type": "library",
      "name": "github.com/inconshreveable/mousetrap",
      "version": "v1.1.0",
      "purl": "pkg:golang/github.com/inconshreveable/mousetrap@v1.1.0?type=module&goos=linux&goarch=amd64",
      "properties": [
        {
          "name": "syft:package:language",
          "value": "go"
        },
        {
          "name": "syft:package:type",
          "value": "go-module"
        }
      ]
    },
    {
      "bom-ref": "pkg:golang/github.com/spf13/cobra@v1.7.0?type=module&goos=linux&goarch=amd64&package-id=d12c4b6f2b186198",
      "type": "library",
      "name": "github.com/spf13/cobra",
      "version": "v1.7.0",
      "purl": "pkg:golang/github.com/spf13/cobra@v1.7.0?type=module&goos=linux&goarch=amd64",
      "properties": [
        {
          "name": "syft:package:language",
          "value": "go"
        },
        {
          "name": "syft:package:type",
          "value": "go-module"
        }
      ]
    },
    {
      "bom-ref": "pkg:golang/github.com/spf13/pflag@v1.0.5?type=module&goos=linux&goarch=amd64&package-id=853dfa7b884273d8",
      "type": "library",
      "name": "github.com/spf13/pflag",
      "version": "v1.0.5",
      "purl": "pkg:golang/github.com/spf13/pflag@v1.0.5?type=module&goos=linux&goarch=amd64",
      "properties": [
        {
          "name": "syft:package:language",
          "value": "go"
        },
        {
          "name": "syft:package:type",
          "value": "go-module"
        }
      ]
    }
  ],
  "dependencies": [
    {
      "ref": "pkg:golang/github.com/inconshreveable/mousetrap@v1.1.0?type=module&goos=linux&goarch=amd64&package-id=4ef988ea2ded80a1",
      "dependsOn": [
        "pkg:golang/github.com/spf13/cobra@v1.7.0?type=module&goos=linux&goarch=amd64&package-id=d12c4b6f2b186198"
      ]
    },
    {
      "ref": "pkg:golang/github.com/spf13/pflag@v1.0.5?type=module&goos=linux&goarch=amd64&package-id=853dfa7b884273d8",
      "dependsOn": [
        "pkg:golang/github.com/spf13/cobra@v1.7.0?type=module&goos=linux&goarch=amd64&package-id=d12c4b6f2b186198"
      ]
    }
  ]
}

What you expected to happen:

I expected the dependency relationships to more or less be intact.

Steps to reproduce the issue:

Taking the json input described above, just run the following to print the difference in a terminal:

$ cat bom.json
$ syft convert bom.json -o cyclonedx-json

Anything else we need to know?:

I tracked down the issue to how CycloneDX dependencies are turned into artifact.Relationship objects in syft/formats/common/cyclonedxhelpers/decoder.go#204:

func collectRelationships(bom *cyclonedx.BOM, s *sbom.SBOM, idMap map[string]interface{}) {
	if bom.Dependencies == nil {
		return
	}
	for _, d := range *bom.Dependencies {
		from, fromExists := idMap[d.Ref].(artifact.Identifiable)
		if !fromExists {
			continue
		}

		if d.Dependencies == nil {
			continue
		}

		for _, t := range *d.Dependencies {
			to, toExists := idMap[t].(artifact.Identifiable)
			if !toExists {
				continue
			}
			s.Relationships = append(s.Relationships, artifact.Relationship{
				From: from,
				To:   to,
				Type: artifact.DependencyOfRelationship, // FIXME this information is lost
			})
		}
	}
}

The above takes the {"ref":"a", "dependsOn":"b"} entries a -- dependsOn --> b and reads it as from:a -- dependencyOf --> to:b, so the meaning of the relationship is reversed. A PR for a fix will come soon.

Environment:

  • Output of grype version:

    Application: syft
    Version: 0.80.0
    JsonSchemaVersion: 7.1.5
    BuildDate: 2023-05-05T17:40:31Z
    GitCommit: 0f1aed4
    GitDescription: v0.80.0
    Platform: linux/amd64
    GoVersion: go1.19.8
    Compiler: gc

  • OS (e.g: cat /etc/os-release or similar):

    NAME="Pop!_OS"
    VERSION="22.04 LTS"
    ID=pop
    ID_LIKE="ubuntu debian"
    PRETTY_NAME="Pop!_OS 22.04 LTS"
    VERSION_ID="22.04"
    HOME_URL="https://pop.system76.com"
    SUPPORT_URL="https://support.system76.com"
    BUG_REPORT_URL="https://github.com/pop-os/pop/issues"
    PRIVACY_POLICY_URL="https://system76.com/privacy"
    VERSION_CODENAME=jammy
    UBUNTU_CODENAME=jammy
    LOGO=distributor-logo-pop-os

@shanealv shanealv added the bug Something isn't working label May 15, 2023
shanealv added a commit to shanealv/syft that referenced this issue May 15, 2023
When reading CycloneDX boms, the relationships defined in the
"dependencies" sections are translated into "artifact.Relationship"
objects. Previously, relationships were inverted by this process. That
is, a CyloneDx dependency "a depends on b" was being read as "a
dependency of b". This caused downstream processing to write out the
dependency relationship incorrectly. This commit fixes the issue by
inverting the relationship during decoding and adding a regression test.

See anchore#1815

Signed-off-by: Shane Alvarez <shane.alv@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant