Reliance on Insufficiently Trustworthy Component

Description

Reliance on Insufficiently Trustworthy Component occurs when a product is built from multiple separate components but uses a component that is not sufficiently trusted to meet expectations for security, reliability, updateability, and maintainability. Products combining multiple components risk incorporating untrustworthy elements—whether third-party hardware, open-source libraries, or internal legacy components. Such components may harbor vulnerabilities that cannot be patched promptly, contain hidden malware, resist updating, or fail specification requirements. Trust assessments vary among stakeholders, creating tradeoffs between security, reliability, safety, and cost.

Risk

Untrustworthy components have severe implications. Supply chain compromise. Hidden vulnerabilities in dependencies. Inability to patch security issues. Malware in third-party code. Lack of security updates. Unknown provenance. Abandoned or unmaintained libraries. License compliance issues. Cascading vulnerabilities. High likelihood when dependency management is neglected.

Solution

Verify that component supply chains employ best practices and that third-party software comes from reputable, actively maintained vendors during requirements and architecture phase. Maintain a Bill of Materials (BOM) and Software Bill of Materials (SBOM)—a formal, machine-readable inventory of software components and dependencies during implementation phase. Continuously monitor component changes, especially vulnerability announcements and end-of-life plans during operation and patching phase.

Common Consequences

ImpactDetails
IntegrityScope: Integrity

Compromised component integrity affecting overall system security.
AvailabilityScope: Availability

Reduced maintainability and inability to patch vulnerabilities.

Example Code

Vulnerable Code

// Vulnerable: package.json with risky dependencies

{
  "name": "vulnerable-app",
  "version": "1.0.0",
  "dependencies": {
    // VULNERABLE: Unmaintained package (no updates in 3+ years)
    "abandoned-lib": "^1.0.0",

    // VULNERABLE: Package with known critical vulnerability
    "lodash": "4.17.15",

    // VULNERABLE: Using wildcard version (unpredictable updates)
    "some-package": "*",

    // VULNERABLE: Git dependency (no version control)
    "git-dep": "git://github.com/user/repo.git",

    // VULNERABLE: Unknown/untrusted publisher
    "shady-npm-pkg": "^2.0.0",

    // VULNERABLE: Very old major version
    "express": "3.0.0"
  }
}
# Vulnerable: Python requirements with risky dependencies

# requirements.txt

# VULNERABLE: No version pinning
requests
django
flask

# VULNERABLE: Using deprecated/unmaintained package
pycrypto==2.6.1  # Deprecated, use pycryptodome

# VULNERABLE: Package with known vulnerabilities
PyYAML==5.3  # CVE-2020-14343

# VULNERABLE: Installing from arbitrary URL
https://example.com/unknown-package.tar.gz

# VULNERABLE: No hash verification
# pip install --no-verify-hashes
// Vulnerable: Java pom.xml with dependency issues

// pom.xml
/*
<dependencies>
    <!-- VULNERABLE: Outdated version with known CVEs -->
    <dependency>
        <groupId>org.apache.struts</groupId>
        <artifactId>struts2-core</artifactId>
        <version>2.3.30</version>  <!-- CVE-2017-5638 -->
    </dependency>

    <!-- VULNERABLE: Using SNAPSHOT (unstable) -->
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>internal-lib</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

    <!-- VULNERABLE: No exclusions for transitive deps -->
    <dependency>
        <groupId>some.group</groupId>
        <artifactId>big-framework</artifactId>
        <version>1.0</version>
        <!-- Pulls in hundreds of transitive dependencies -->
    </dependency>
</dependencies>
*/
// Vulnerable: Go with unverified dependencies

// go.mod

// VULNERABLE: Using pseudo-version (untagged commit)
// require github.com/user/repo v0.0.0-20200101010101-abcdef123456

// VULNERABLE: Replace directive pointing to local/arbitrary code
// replace github.com/original/repo => /local/path/to/code
// replace github.com/original/repo => github.com/fork/repo

// Vulnerable code using unverified package
package main

import (
    // VULNERABLE: Import from unknown source
    "github.com/random-user/untrusted-crypto"
)

func main() {
    // Using potentially compromised cryptographic library
    key := untrusted_crypto.GenerateKey()
    // ...
}

Fixed Code

// Fixed: package.json with secure dependency management

{
  "name": "secure-app",
  "version": "1.0.0",
  "dependencies": {
    // FIXED: Pinned versions from reputable maintainers
    "lodash": "4.17.21",
    "express": "4.18.2",

    // FIXED: Actively maintained alternatives
    "axios": "1.4.0"
  },
  "devDependencies": {
    // FIXED: Security scanning tools
    "npm-audit": "^1.0.0",
    "snyk": "^1.1000.0"
  },
  "scripts": {
    // FIXED: Security checks in CI/CD
    "security-check": "npm audit && snyk test",
    "preinstall": "npm audit"
  },
  "engines": {
    // FIXED: Specify supported Node.js versions
    "node": ">=18.0.0"
  }
}

// package-lock.json provides:
// - Exact versions for all dependencies
// - Integrity hashes (SHA-512)
// - Reproducible builds
# Fixed: Python requirements with security practices

# requirements.txt with pinned versions and hashes

# FIXED: Pinned versions with hash verification
requests==2.31.0 \
    --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f

django==4.2.5 \
    --hash=sha256:b6b2b5cae821077f137dc4898c6b46a3b4e2d2ae0f0eb9a5e6e0e0d3c8a5d4f1

# FIXED: Using maintained cryptographic library
pycryptodome==3.19.0 \
    --hash=sha256:abcdef1234567890

# FIXED: Safe YAML library
PyYAML==6.0.1 \
    --hash=sha256:1234567890abcdef

# requirements-dev.txt
# FIXED: Security scanning tools
safety==2.3.5
bandit==1.7.5
pip-audit==2.6.1
# Fixed: Python dependency verification

import subprocess
import hashlib
import json
from typing import Dict, List

class DependencyVerifier:
    """FIXED: Verify dependencies before use."""

    def __init__(self, sbom_path: str):
        self.sbom = self._load_sbom(sbom_path)

    def _load_sbom(self, path: str) -> Dict:
        """FIXED: Load Software Bill of Materials."""
        with open(path, 'r') as f:
            return json.load(f)

    def verify_all_dependencies(self) -> List[str]:
        """FIXED: Check all dependencies against SBOM."""
        issues = []

        for dep in self.sbom.get('dependencies', []):
            name = dep['name']
            expected_version = dep['version']
            expected_hash = dep.get('hash')

            # FIXED: Verify installed version matches SBOM
            installed = self._get_installed_version(name)
            if installed != expected_version:
                issues.append(f"{name}: version mismatch "
                            f"(expected {expected_version}, got {installed})")

            # FIXED: Verify integrity hash
            if expected_hash:
                actual_hash = self._compute_package_hash(name)
                if actual_hash != expected_hash:
                    issues.append(f"{name}: hash mismatch")

            # FIXED: Check for known vulnerabilities
            vulns = self._check_vulnerabilities(name, expected_version)
            if vulns:
                issues.extend(vulns)

        return issues

    def _check_vulnerabilities(self, name: str, version: str) -> List[str]:
        """FIXED: Check against vulnerability database."""
        # Use safety/pip-audit/etc. to check
        result = subprocess.run(
            ['pip-audit', '--requirement', '-', '--strict'],
            input=f'{name}=={version}\n',
            capture_output=True,
            text=True
        )
        if result.returncode != 0:
            return [f"{name}: {result.stdout}"]
        return []

    def generate_sbom(self, output_path: str):
        """FIXED: Generate SBOM in CycloneDX format."""
        subprocess.run([
            'cyclonedx-py',
            '--format', 'json',
            '--output', output_path
        ], check=True)

# Usage
verifier = DependencyVerifier('sbom.json')
issues = verifier.verify_all_dependencies()
if issues:
    print("Dependency verification failed:")
    for issue in issues:
        print(f"  - {issue}")
    exit(1)
// Fixed: Java pom.xml with secure dependency management

/*
<project>
    <properties>
        <!-- FIXED: Centralized version management -->
        <spring.version>6.0.11</spring.version>
        <jackson.version>2.15.2</jackson.version>
    </properties>

    <dependencyManagement>
        <!-- FIXED: Use BOM for consistent versions -->
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-framework-bom</artifactId>
                <version>${spring.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- FIXED: Updated, patched version -->
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-core</artifactId>
            <version>6.3.0</version>
        </dependency>

        <!-- FIXED: Exclude vulnerable transitive dependencies -->
        <dependency>
            <groupId>some.group</groupId>
            <artifactId>big-framework</artifactId>
            <version>2.0</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-collections</groupId>
                    <artifactId>commons-collections</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- FIXED: Replace excluded dep with safe version -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.4</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- FIXED: OWASP Dependency Check -->
            <plugin>
                <groupId>org.owasp</groupId>
                <artifactId>dependency-check-maven</artifactId>
                <version>8.4.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>check</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <failBuildOnCVSS>7</failBuildOnCVSS>
                </configuration>
            </plugin>

            <!-- FIXED: Enforce dependency convergence -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-enforcer-plugin</artifactId>
                <version>3.4.1</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>enforce</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <dependencyConvergence/>
                                <banDuplicatePomDependencyVersions/>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
*/
// Fixed: Go with verified dependencies

// go.mod with proper versioning

/*
module example.com/secure-app

go 1.21

// FIXED: Use tagged releases
require (
    github.com/go-chi/chi/v5 v5.0.10
    golang.org/x/crypto v0.14.0
)

// FIXED: go.sum provides hash verification automatically
// Run: go mod verify
*/

// Fixed: Dependency verification in CI/CD
package main

import (
    "fmt"
    "os/exec"
)

func verifyDependencies() error {
    // FIXED: Verify module checksums
    cmd := exec.Command("go", "mod", "verify")
    if err := cmd.Run(); err != nil {
        return fmt.Errorf("module verification failed: %w", err)
    }

    // FIXED: Check for vulnerabilities using govulncheck
    cmd = exec.Command("govulncheck", "./...")
    output, err := cmd.CombinedOutput()
    if err != nil {
        return fmt.Errorf("vulnerability check failed: %s", output)
    }

    // FIXED: Verify no replace directives point to untrusted sources
    cmd = exec.Command("go", "mod", "graph")
    // Parse and validate...

    return nil
}

// FIXED: SBOM generation
func generateSBOM(outputPath string) error {
    // Use cyclonedx-gomod or similar
    cmd := exec.Command("cyclonedx-gomod", "mod", "-json", "-output", outputPath)
    return cmd.Run()
}

CVE Examples

  • CVE-2021-44228: Log4Shell - Critical vulnerability in widely-used Apache Log4j library.
  • CVE-2020-8203: Prototype pollution in Lodash affecting millions of applications.
  • CVE-2017-5638: Apache Struts vulnerability exploited in Equifax breach.

  • CWE-710: Improper Adherence to Coding Standards (parent)
  • CWE-1104: Use of Unmaintained Third Party Components (child)
  • CWE-1329: Reliance on Component That is Not Updateable (child)

References

  1. MITRE Corporation. "CWE-1357: Reliance on Insufficiently Trustworthy Component." https://cwe.mitre.org/data/definitions/1357.html
  2. OWASP. "Software Component Verification Standard (SCVS)"
  3. NTIA. "Software Bill of Materials (SBOM)"