Detect supply chain security vulnerabilities: dependency vulnerabilities, certificate pinning bypass, and XXE (XML External Entity) attacks. Trigger when reviewing dependency updates, package.json/requirements.txt changes, XML parsing code, mobile network security config, or any code handling third-party dependencies and XML processing.
Review code for supply chain security issues: vulnerable dependencies, missing or bypassable certificate pinning in mobile apps, and XML External Entity (XXE) injection attacks.
This skill covers three supply chain security classes:
*, latest, ^1.x)High-risk patterns:
// ❌ UNSAFE: Wildcard versions
{
"dependencies": {
"lodash": "*",
"express": "^4.0.0"
}
}
High-risk patterns (Android):
<!-- ❌ UNSAFE: No pinning -->
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
High-risk patterns (iOS):
// ❌ UNSAFE: Trust all certificates
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
}
High-risk patterns:
// ❌ UNSAFE: XXE vulnerable
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(userUploadedFile);
# ❌ UNSAFE: XXE vulnerable
import xml.etree.ElementTree as ET
tree = ET.parse(user_file)
Check for known vulnerabilities:
# Node.js
npm audit
npm audit fix
# Python
pip-audit
safety check
# Java
mvn dependency-check:check
# Ruby
bundle audit
Check version pinning:
// ❌ UNSAFE: Unpinned
{
"dependencies": {
"axios": "^1.0.0", // Could install 1.9.9 with vulnerabilities
"lodash": "*"
}
}
// ✅ SAFE: Pinned with lock file
{
"dependencies": {
"axios": "1.6.0"
}
}
// + package-lock.json present
Check for lock files:
Android - Check network_security_config.xml:
<!-- ✅ SAFE: Pinning configured -->
<network-security-config>
<domain-config>
<domain includeSubdomains="true">api.example.com</domain>
<pin-set expiration="2025-12-31">
<pin digest="SHA-256">base64==</pin>
<pin digest="SHA-256">backup-pin==</pin>
</pin-set>
</domain-config>
</network-security-config>
Android - Check OkHttp:
// ✅ SAFE: OkHttp pinning
val certificatePinner = CertificatePinner.Builder()
.add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.add("api.example.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=")
.build()
val client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()
iOS - Check URLSession delegate:
// ✅ SAFE: Public key pinning
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard let serverTrust = challenge.protectionSpace.serverTrust,
let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0) else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
let serverPublicKey = SecCertificateCopyKey(certificate)
let pinnedKeys: [SecKey] = loadPinnedKeys()
if pinnedKeys.contains(where: { $0 == serverPublicKey }) {
completionHandler(.useCredential, URLCredential(trust: serverTrust))
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}
}
Check XML parser configuration:
Java:
// ✅ SAFE: XXE disabled
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);
Python:
# ✅ SAFE: defusedxml
from defusedxml.ElementTree import parse
tree = parse(user_file)
# ❌ UNSAFE: Standard library
import xml.etree.ElementTree as ET
tree = ET.parse(user_file)
Node.js:
// ✅ SAFE: xml2js with XXE prevention
const xml2js = require('xml2js');
const parser = new xml2js.Parser({
explicitCharkey: false,
trim: false,
normalize: false,
normalizeTags: false,
attrkey: '@',
charkey: '#',
explicitArray: false,
ignoreAttrs: false,
mergeAttrs: false,
explicitRoot: false,
validator: null,
xmlns: false,
explicitChildren: false,
childkey: '$$',
charkey: '_',
attrNameProcessors: null,
attrValueProcessors: null,
tagNameProcessors: null,
valueProcessors: null,
emptyTag: null,
strict: true,
xmlns: false,
resolveUri: false // Prevent XXE
});
{
"dependencies": {
"express": "4.18.2",
"lodash": "4.17.21"
},
"scripts": {
"preinstall": "npm audit --audit-level=high"
}
}
With: package-lock.json committed, CI runs npm audit before deploy.
{
"dependencies": {
"express": "*",
"lodash": "^4.0.0"
}
}
Finding: High — Wildcard versions without lock file. Vulnerable versions could be installed.
val certificatePinner = CertificatePinner.Builder()
.add("api.production.com", "sha256/PrimaryPin==")
.add("api.production.com", "sha256/BackupPin==")
.build()
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
})
Finding: Critical — Custom TrustManager trusts all certificates. MitM attacks possible.
from defusedxml.ElementTree import parse
tree = parse(uploaded_file)
import xml.etree.ElementTree as ET
tree = ET.parse(uploaded_file)
Finding: High — XXE vulnerability. Attacker can read local files via external entity injection.