Skip to main content
TPN Parser Configuration TemplateResearch
5 min readFor Compliance Teams

TPN Parser Configuration Template

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 pdfplumber and regex libraries
  • 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.

Topics:Research

You Might Also Like