Purpose of the Template
Your Third-Party Notices (TPNs) likely sit in a compliance folder as a lengthy PDF with inconsistent formatting. While they're generated for legal reasons, they don't contribute to your security posture. This template provides a configuration to parse TPNs into structured data you can query. Instead of manually searching PDFs for license violations or vulnerable components, you'll extract component names, versions, and licenses into a format your security tools can use.
This is important because TPNs often list dependencies not found in your Software Bill of Materials (SBOMs). If you're using closed-source SDKs or vendor libraries, the TPN might be your only source for what's bundled in the binary.
Prerequisites
Before implementing this parser, ensure you have the following:
Technical Requirements:
- Python 3.9+ with
pdfplumberandregexlibraries - Access to your build artifacts directory where TPNs are generated
- A structured output target (JSON file, database, or SBOM tool API)
Process Requirements:
- A documented TPN generation process (which build step creates them, what format)
- Sample TPNs from at least three different components in your stack
- Agreement with your compliance team on what constitutes a "high-risk" license
Knowledge Requirements:
- Basic understanding of open source license categories (permissive vs. copyleft)
- Familiarity with your organization's approved license list
- Contact information for the person handling license compliance escalations
Configuration Template
# tpn_parser_config.yaml
# Configuration for extracting structured data from Third-Party Notices
parser:
input_format: pdf # pdf, html, or txt
encoding: utf-8
# Layout detection settings
layout:
multi_column: true
column_threshold: 0.4 # Fraction of page width to detect columns
preserve_whitespace: false
# Component extraction patterns
component_patterns:
# Match "Component: name version" or "name (version)"
- regex: '(?:Component:|Package:)\s*([A-Za-z0-9._-]+)\s+(?:v?(\d+\.\d+[.\d]*))'
name_group: 1
version_group: 2
# Match "name-version" format common in npm
- regex: '([a-z0-9-]+)-(\d+\.\d+\.\d+)'
name_group: 1
version_group: 2
# License extraction patterns
license_patterns:
# Exact matches for common licenses
permissive:
- 'MIT License'
- 'Apache License 2.0'
- 'BSD 3-Clause'
- 'BSD 2-Clause'
- 'ISC License'
copyleft_weak:
- 'LGPL-2.1'
- 'LGPL-3.0'
- 'MPL-2.0'
copyleft_strong:
- 'GPL-2.0'
- 'GPL-3.0'
- 'AGPL-3.0'
# Fuzzy matching threshold for license text
similarity_threshold: 0.85
# URL extraction for upstream sources
url_patterns:
- regex: 'https?://github\.com/[\w-]+/[\w-]+'
- regex: 'https?://(?:www\.)?npmjs\.com/package/[\w-]+'
- regex: 'https?://pypi\.org/project/[\w-]+'
# Output configuration
output:
format: json # json, spdx, or cyclonedx
# Fields to include in output
fields:
- component_name
- component_version
- license_type
- license_category # permissive, copyleft_weak, copyleft_strong
- source_url
- extraction_confidence # 0.0 to 1.0
# Filtering rules
filters:
min_confidence: 0.75
exclude_licenses: [] # Add licenses to skip, e.g., ['Public Domain']
# Enrichment from external sources
enrich:
enabled: true
sources:
- type: osv_api
endpoint: 'https://api.osv.dev/v1/query'
check_vulnerabilities: true
- type: deps_dev
endpoint: 'https://api.deps.dev/v3alpha'
fetch_metadata: true
# Quality controls
validation:
# Require these fields to be present
required_fields:
- component_name
- license_type
# Flag components for manual review
review_triggers:
- copyleft_strong_license: true
- missing_version: true
- confidence_below: 0.80
- unknown_license: true
# Duplicate detection
deduplication:
enabled: true
match_on: [component_name, component_version]
# Integration settings
integration:
# Push results to existing tools
sbom_tools:
- name: dependency_track
api_endpoint: 'https://dtrack.yourorg.com/api/v1'
project_uuid: 'REPLACE_WITH_YOUR_PROJECT_UUID'
auto_create_components: false
# Notification channels
notifications:
high_risk_licenses:
- type: slack
webhook: 'REPLACE_WITH_WEBHOOK_URL'
channel: '#security-alerts'
- type: email
recipients: ['[email protected]']
parsing_errors:
- type: email
recipients: ['[email protected]']
Customizing the Template
Start with your TPN samples. Open three different TPNs from your stack and check:
- Are component names on their own line or inline with license text?
- Do versions use semantic versioning (1.2.3) or date-based (2024.1)?
- Are licenses spelled out ("MIT License") or abbreviated ("MIT")?
Adjust the component_patterns and license_patterns sections to match what you see. If your vendor uses "Library:" instead of "Component:", add that pattern.
Set your license categories correctly. The copyleft_strong list is vital for compliance. If your organization treats AGPL-3.0 differently than GPL-3.0, split them into separate categories. If Mozilla Public License 2.0 is acceptable, move it to permissive or create a new approved_copyleft category.
Configure confidence thresholds based on your risk tolerance. The source research achieved 92-96% accuracy for permissive licenses and 85-90% for copyleft detection. Start with min_confidence: 0.75 and review what gets flagged. Adjust if you're seeing too many false positives or critical components slipping through.
Integrate with your existing tools. If you're using Dependency-Track, OWASP Dependency-Check, or a commercial SBOM platform, use the integration.sbom_tools section to push parsed data directly. This prevents TPNs from becoming another silo.
Don't skip the review triggers. Set review_triggers based on what creates legal or security risk in your environment. If you're shipping a SaaS product, AGPL-3.0 components need immediate review. If you're building internal tools, your threshold might differ.
Validation Steps
After configuring the parser, validate it before production use:
1. Baseline accuracy check
- Run the parser on five representative TPNs.
- Manually verify the first 20 components extracted from each.
- Calculate your actual accuracy rate: (correct extractions / total extractions).
- If below 85%, revisit your regex patterns.
2. License categorization audit
- Export all unique licenses detected.
- Review each one with your compliance team.
- Confirm the category assignment matches your organization's interpretation.
- Document any edge cases (e.g., dual-licensed components).
3. Integration test
- Parse a TPN and push results to your SBOM tool.
- Verify components appear correctly in the tool's UI.
- Check that vulnerability lookups work (if configured).
- Confirm notification channels fire for test cases.
4. False positive review
- Identify components flagged for manual review.
- Determine how many are actual risks vs. parsing errors.
- If more than 30% are false positives, adjust your confidence threshold or patterns.
5. Coverage comparison
- For one application, compare the TPN output to your existing SBOM.
- Document components that appear only in the TPN.
- Investigate why those components aren't in your SBOM pipeline.
- This gap analysis often reveals bundled dependencies or vendored code you didn't know about.
Run this validation quarterly or whenever you onboard a new vendor whose TPN format differs significantly from your existing samples. TPNs aren't standardized like SPDX, so you'll need to adapt patterns as your dependency landscape changes.



