• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pantsbuild / pants / 19381742489

15 Nov 2025 12:52AM UTC coverage: 49.706% (-30.6%) from 80.29%
19381742489

Pull #22890

github

web-flow
Merge d961abf79 into 42e1ebd41
Pull Request #22890: Updated all python subsystem constraints to 3.14

4 of 5 new or added lines in 5 files covered. (80.0%)

14659 existing lines in 485 files now uncovered.

31583 of 63540 relevant lines covered (49.71%)

0.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.27
/src/python/pants/backend/tools/trufflehog/rules_integration_test.py
1
# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3
from __future__ import annotations
1✔
4

5
from typing import Any
1✔
6

7
import pytest
1✔
8

9
from pants.backend.tools.trufflehog.rules import TrufflehogRequest
1✔
10
from pants.backend.tools.trufflehog.rules import rules as trufflehog_rules
1✔
11
from pants.core.goals.fmt import Partitions
1✔
12
from pants.core.goals.lint import LintResult
1✔
13
from pants.core.util_rules import config_files, external_tool
1✔
14
from pants.engine.fs import PathGlobs
1✔
15
from pants.engine.internals.native_engine import Snapshot
1✔
16
from pants.testutil.rule_runner import QueryRule, RuleRunner
1✔
17

18

19
@pytest.fixture
1✔
20
def rule_runner() -> RuleRunner:
1✔
21
    return RuleRunner(
1✔
22
        rules=[
23
            *trufflehog_rules(),
24
            *config_files.rules(),
25
            *external_tool.rules(),
26
            QueryRule(Partitions, [TrufflehogRequest.PartitionRequest]),
27
            QueryRule(LintResult, [TrufflehogRequest.Batch]),
28
        ],
29
    )
30

31

32
PANTS_TOML = """[GLOBAL]\nbackend_packages = ["pants.backend.tools.trufflehog"]\n"""
1✔
33

34
# This configuration file specifies a detector that looks for custom regex patterns
35
TRUFFLEHOG_CONFIG = r"""
1✔
36
# config.yaml
37
detectors:
38
  - name: HogTokenDetector
39
    keywords:
40
      - hog
41
    regex:
42
      hogID: '\b(HOG[0-9A-Z]{17})\b'
43
      hogToken: '[^A-Za-z0-9+\/]{0,1}([A-Za-z0-9+\/]{40})[^A-Za-z0-9+\/]{0,1}'
44
    verify:
45
      - endpoint: http://localhost:8000/
46
        # unsafe must be set if the endpoint is HTTP
47
        unsafe: true
48
        headers:
49
          - "Authorization: super secret authorization header"
50
"""
51

52
# Example file contents with mock secrets in place for detection. These are not real secrets.
53
TRUFFLEHOG_PAYLOAD_WITH_SECRETS = """
1✔
54
{
55
    "HogTokenDetector": {
56
        "HogID": ["HOGAAIUNNWHAHJJWUQYR"],
57
        "HogSecret": ["sD9vzqdSsAOxntjAJ/qZ9sw+8PvEYg0r7D1Hhh0C"],
58
    }
59
}
60
"""
61

62
# The count of detectors loaded by the current version of Trufflehog.
63
# This may change in future versions, depending on whether or not new detectors are added.
64
TOTAL_DETECTORS = 738
1✔
65

66

67
def run_trufflehog(
1✔
68
    rule_runner: RuleRunner,
69
    *,
70
    extra_args: list[str] | None = None,
71
) -> LintResult:
72
    rule_runner.set_options(
1✔
73
        ["--backend-packages=pants.backend.tools.trufflehog", *(extra_args or ())],
74
    )
75
    snapshot = rule_runner.request(Snapshot, [PathGlobs(["**"])])
1✔
76
    partition = rule_runner.request(
1✔
77
        Partitions[Any], [TrufflehogRequest.PartitionRequest(snapshot.files)]
78
    )[0]
79
    fmt_result = rule_runner.request(
1✔
80
        LintResult,
81
        [
82
            TrufflehogRequest.Batch("", partition.elements, partition_metadata=partition.metadata),
83
        ],
84
    )
85
    return fmt_result
1✔
86

87

88
def extract_total_detector_count(input_string: str) -> int | None:
1✔
89
    """This function extracts the total number of detectors loaded by Trufflehog.
90

91
    Trufflehog prints to stderr in a format that can't be parsed as json.
92
    """
93
    # Find the index of the substring "total"
UNCOV
94
    total_index = input_string.find('"total":')
×
UNCOV
95
    if total_index == -1:
×
96
        return None  # "total" key not found
×
97

98
    # Extract the value after "total"
UNCOV
99
    total_value = ""
×
UNCOV
100
    for char in input_string[total_index + len('"total":') :]:
×
UNCOV
101
        if char.isdigit():
×
UNCOV
102
            total_value += char
×
103
        else:
UNCOV
104
            break
×
105

UNCOV
106
    return int(total_value) if total_value else None
×
107

108

109
def test_detectors_loaded(rule_runner: RuleRunner) -> None:
1✔
UNCOV
110
    rule_runner.write_files({"pants-enable-trufflehog.toml": PANTS_TOML})
×
UNCOV
111
    fmt_result = run_trufflehog(rule_runner)
×
UNCOV
112
    assert not fmt_result.stdout
×
113
    # Trufflehog prints details on how many active detectors are running to stderr
UNCOV
114
    assert "loaded detectors" in fmt_result.stderr
×
115
    # This number is expected to change with upgrades to trufflehog
UNCOV
116
    assert TOTAL_DETECTORS == extract_total_detector_count(fmt_result.stderr)
×
UNCOV
117
    rule_runner.write_files(
×
118
        {
119
            "pants-enable-trufflehog.toml.toml": PANTS_TOML,
120
            "trufflehog-config.yaml": TRUFFLEHOG_CONFIG,
121
        }
122
    )
UNCOV
123
    fmt_result = run_trufflehog(rule_runner)
×
UNCOV
124
    assert not fmt_result.stdout
×
125
    # Adding the config file has added one additional detector
UNCOV
126
    assert TOTAL_DETECTORS + 1 == extract_total_detector_count(fmt_result.stderr)
×
127

128

129
@pytest.mark.platform_specific_behavior
1✔
130
def test_secret_detected(rule_runner: RuleRunner) -> None:
1✔
131
    # Write the configuration file
132
    rule_runner.write_files(
1✔
133
        {
134
            "pants-enable-trufflehog.toml.toml": PANTS_TOML,
135
            "trufflehog-config.yaml": TRUFFLEHOG_CONFIG,
136
            "secret.json": TRUFFLEHOG_PAYLOAD_WITH_SECRETS,
137
        }
138
    )
139
    fmt_result = run_trufflehog(rule_runner)
1✔
140

141
    # Trufflehog returns exit code 183 upon finding secrets
142
    assert fmt_result.exit_code == 183
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc