Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # 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:

@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>
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant