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
| Impact | Details |
|---|---|
| Integrity | Scope: Integrity Compromised component integrity affecting overall system security. |
| Availability | Scope: 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.
Related CWEs
- 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
- MITRE Corporation. "CWE-1357: Reliance on Insufficiently Trustworthy Component." https://cwe.mitre.org/data/definitions/1357.html
- OWASP. "Software Component Verification Standard (SCVS)"
- NTIA. "Software Bill of Materials (SBOM)"