leftblock 0.4.2__tar.gz → 0.4.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. {leftblock-0.4.2 → leftblock-0.4.3}/PKG-INFO +4 -4
  2. {leftblock-0.4.2 → leftblock-0.4.3}/README.md +3 -3
  3. {leftblock-0.4.2 → leftblock-0.4.3}/leftblock/cli.py +1 -1
  4. {leftblock-0.4.2 → leftblock-0.4.3}/leftblock/data/gitleaks.toml +6 -0
  5. {leftblock-0.4.2 → leftblock-0.4.3}/leftblock.egg-info/PKG-INFO +4 -4
  6. {leftblock-0.4.2 → leftblock-0.4.3}/pyproject.toml +1 -1
  7. {leftblock-0.4.2 → leftblock-0.4.3}/tests/test_bypasses.py +1 -1
  8. {leftblock-0.4.2 → leftblock-0.4.3}/tests/test_kanbus_advice.py +1 -1
  9. {leftblock-0.4.2 → leftblock-0.4.3}/tests/test_recorded_overrides.py +3 -3
  10. {leftblock-0.4.2 → leftblock-0.4.3}/tests/test_sensitive_rules.py +23 -6
  11. {leftblock-0.4.2 → leftblock-0.4.3}/LICENSE +0 -0
  12. {leftblock-0.4.2 → leftblock-0.4.3}/leftblock/__init__.py +0 -0
  13. {leftblock-0.4.2 → leftblock-0.4.3}/leftblock/allow.py +0 -0
  14. {leftblock-0.4.2 → leftblock-0.4.3}/leftblock/bypass.py +0 -0
  15. {leftblock-0.4.2 → leftblock-0.4.3}/leftblock/core.py +0 -0
  16. {leftblock-0.4.2 → leftblock-0.4.3}/leftblock/hooks.py +0 -0
  17. {leftblock-0.4.2 → leftblock-0.4.3}/leftblock/merge.py +0 -0
  18. {leftblock-0.4.2 → leftblock-0.4.3}/leftblock.egg-info/SOURCES.txt +0 -0
  19. {leftblock-0.4.2 → leftblock-0.4.3}/leftblock.egg-info/dependency_links.txt +0 -0
  20. {leftblock-0.4.2 → leftblock-0.4.3}/leftblock.egg-info/entry_points.txt +0 -0
  21. {leftblock-0.4.2 → leftblock-0.4.3}/leftblock.egg-info/requires.txt +0 -0
  22. {leftblock-0.4.2 → leftblock-0.4.3}/leftblock.egg-info/top_level.txt +0 -0
  23. {leftblock-0.4.2 → leftblock-0.4.3}/setup.cfg +0 -0
  24. {leftblock-0.4.2 → leftblock-0.4.3}/tests/test_branding.py +0 -0
  25. {leftblock-0.4.2 → leftblock-0.4.3}/tests/test_commit_gate.py +0 -0
  26. {leftblock-0.4.2 → leftblock-0.4.3}/tests/test_default_config.py +0 -0
  27. {leftblock-0.4.2 → leftblock-0.4.3}/tests/test_false_positives.py +0 -0
  28. {leftblock-0.4.2 → leftblock-0.4.3}/tests/test_install.py +0 -0
  29. {leftblock-0.4.2 → leftblock-0.4.3}/tests/test_local_install.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: leftblock
3
- Version: 0.4.2
3
+ Version: 0.4.3
4
4
  Summary: LeftBlock: a pluggable inspection gate for Git commits
5
5
  License: MIT License
6
6
 
@@ -124,7 +124,7 @@ configures the integration; it does not install scanner binaries.
124
124
  In the intended Python environment:
125
125
 
126
126
  ```bash
127
- python -m pip install leftblock==0.4.2
127
+ python -m pip install leftblock==0.4.3
128
128
  python -m leftblock.cli --help
129
129
  ```
130
130
 
@@ -397,7 +397,7 @@ PEM private keys, and other standard secret formats.
397
397
 
398
398
  | Rule | What it catches |
399
399
  |---|---|
400
- | `leftblock-personal-email` | Personal email addresses (infrastructure identities like `git@github.com`, `@users.noreply.github.com`, no-reply addresses and `@example.*` placeholders are allowlisted) |
400
+ | `leftblock-personal-email` | Personal email addresses (infrastructure identities like `git@github.com`, `@users.noreply.github.com`, no-reply addresses, `@example.*` placeholders, `@example.edu` and any address on a `.test`, `.example`, `.invalid` or `.localhost` domain are allowlisted) |
401
401
  | `leftblock-home-path-posix` | Home-folder paths `/Users/<name>`, `/home/<name>` |
402
402
  | `leftblock-home-path-windows` | `C:\Users\<name>` and `\Users\<name>` |
403
403
  | `leftblock-session-uuid` | Potential session UUIDs (not flagged in Kanbus board data; example values and the `.kanbus.yml` `project_id` line are also allowed) |
@@ -409,7 +409,7 @@ PEM private keys, and other standard secret formats.
409
409
  | `leftblock-bip39-mnemonic` | BIP-39 seed phrases (12–24 words) in seed/mnemonic/recovery context |
410
410
 
411
411
  A blocked check prints a one-line hint after each rule's findings (once per
412
- rule): use a role or placeholder address for personal emails; a relative path,
412
+ rule): use a role address or a reserved placeholder for personal emails; a relative path,
413
413
  `$HOME` or `~` for home paths; drop or describe session and actor identifiers;
414
414
  and for API, private and wallet keys, remove the value **and rotate the key**,
415
415
  since it may already be exposed. Findings in Kanbus board data
@@ -91,7 +91,7 @@ configures the integration; it does not install scanner binaries.
91
91
  In the intended Python environment:
92
92
 
93
93
  ```bash
94
- python -m pip install leftblock==0.4.2
94
+ python -m pip install leftblock==0.4.3
95
95
  python -m leftblock.cli --help
96
96
  ```
97
97
 
@@ -364,7 +364,7 @@ PEM private keys, and other standard secret formats.
364
364
 
365
365
  | Rule | What it catches |
366
366
  |---|---|
367
- | `leftblock-personal-email` | Personal email addresses (infrastructure identities like `git@github.com`, `@users.noreply.github.com`, no-reply addresses and `@example.*` placeholders are allowlisted) |
367
+ | `leftblock-personal-email` | Personal email addresses (infrastructure identities like `git@github.com`, `@users.noreply.github.com`, no-reply addresses, `@example.*` placeholders, `@example.edu` and any address on a `.test`, `.example`, `.invalid` or `.localhost` domain are allowlisted) |
368
368
  | `leftblock-home-path-posix` | Home-folder paths `/Users/<name>`, `/home/<name>` |
369
369
  | `leftblock-home-path-windows` | `C:\Users\<name>` and `\Users\<name>` |
370
370
  | `leftblock-session-uuid` | Potential session UUIDs (not flagged in Kanbus board data; example values and the `.kanbus.yml` `project_id` line are also allowed) |
@@ -376,7 +376,7 @@ PEM private keys, and other standard secret formats.
376
376
  | `leftblock-bip39-mnemonic` | BIP-39 seed phrases (12–24 words) in seed/mnemonic/recovery context |
377
377
 
378
378
  A blocked check prints a one-line hint after each rule's findings (once per
379
- rule): use a role or placeholder address for personal emails; a relative path,
379
+ rule): use a role address or a reserved placeholder for personal emails; a relative path,
380
380
  `$HOME` or `~` for home paths; drop or describe session and actor identifiers;
381
381
  and for API, private and wallet keys, remove the value **and rotate the key**,
382
382
  since it may already be exposed. Findings in Kanbus board data
@@ -335,7 +335,7 @@ _REMOVE_AND_ROTATE = "Remove it AND rotate the key: it may already be exposed."
335
335
  _HOME_PATH = "Use a relative path, $HOME or ~ instead."
336
336
  _DESCRIBE_ID = "Drop the identifier or describe it instead."
337
337
  RULE_HINTS = {
338
- "leftblock-personal-email": "Use a role or placeholder address, or describe it instead.",
338
+ "leftblock-personal-email": "Use a role address or a reserved placeholder (example.com/.org/.net, or any .test, .example or .invalid domain), or describe it instead.",
339
339
  "leftblock-home-path-posix": _HOME_PATH,
340
340
  "leftblock-home-path-windows": _HOME_PATH,
341
341
  "leftblock-session-uuid": _DESCRIBE_ID,
@@ -67,6 +67,12 @@ regexes = [
67
67
  '''(^|[^a-zA-Z0-9._%+\-'])no-?reply@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}''',
68
68
  '''git@github\.com''',
69
69
  '''@(example|github)\.(com|org|net|io|ai)''',
70
+ # Domains reserved for documentation and testing: the TLDs .test, .example,
71
+ # .invalid and .localhost (RFC 2606 section 2, RFC 6761 section 6) at any
72
+ # subdomain depth, and example.edu (RFC 2606 section 3). Anchored on the end
73
+ # of the address so look-alikes such as test.com or example.test.co still flag.
74
+ '''@(?:[a-zA-Z0-9\-]+\.)*(?:test|example|invalid|localhost)$''',
75
+ '''@example\.edu$''',
70
76
  ]
71
77
 
72
78
  [[rules]]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: leftblock
3
- Version: 0.4.2
3
+ Version: 0.4.3
4
4
  Summary: LeftBlock: a pluggable inspection gate for Git commits
5
5
  License: MIT License
6
6
 
@@ -124,7 +124,7 @@ configures the integration; it does not install scanner binaries.
124
124
  In the intended Python environment:
125
125
 
126
126
  ```bash
127
- python -m pip install leftblock==0.4.2
127
+ python -m pip install leftblock==0.4.3
128
128
  python -m leftblock.cli --help
129
129
  ```
130
130
 
@@ -397,7 +397,7 @@ PEM private keys, and other standard secret formats.
397
397
 
398
398
  | Rule | What it catches |
399
399
  |---|---|
400
- | `leftblock-personal-email` | Personal email addresses (infrastructure identities like `git@github.com`, `@users.noreply.github.com`, no-reply addresses and `@example.*` placeholders are allowlisted) |
400
+ | `leftblock-personal-email` | Personal email addresses (infrastructure identities like `git@github.com`, `@users.noreply.github.com`, no-reply addresses, `@example.*` placeholders, `@example.edu` and any address on a `.test`, `.example`, `.invalid` or `.localhost` domain are allowlisted) |
401
401
  | `leftblock-home-path-posix` | Home-folder paths `/Users/<name>`, `/home/<name>` |
402
402
  | `leftblock-home-path-windows` | `C:\Users\<name>` and `\Users\<name>` |
403
403
  | `leftblock-session-uuid` | Potential session UUIDs (not flagged in Kanbus board data; example values and the `.kanbus.yml` `project_id` line are also allowed) |
@@ -409,7 +409,7 @@ PEM private keys, and other standard secret formats.
409
409
  | `leftblock-bip39-mnemonic` | BIP-39 seed phrases (12–24 words) in seed/mnemonic/recovery context |
410
410
 
411
411
  A blocked check prints a one-line hint after each rule's findings (once per
412
- rule): use a role or placeholder address for personal emails; a relative path,
412
+ rule): use a role address or a reserved placeholder for personal emails; a relative path,
413
413
  `$HOME` or `~` for home paths; drop or describe session and actor identifiers;
414
414
  and for API, private and wallet keys, remove the value **and rotate the key**,
415
415
  since it may already be exposed. Findings in Kanbus board data
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "leftblock"
7
- version = "0.4.2"
7
+ version = "0.4.3"
8
8
  description = "LeftBlock: a pluggable inspection gate for Git commits"
9
9
  readme = "README.md"
10
10
  license = {file = "LICENSE"}
@@ -10,7 +10,7 @@ from leftblock import bypass
10
10
  from test_commit_gate import GITLEAKS, RepositoryFixture
11
11
 
12
12
  MARKER = "gitleaks" + ":allow"
13
- EMAIL = "info" + "@" + "public-role.test"
13
+ EMAIL = "info" + "@" + "public-role" + ".co"
14
14
  REASON = "Reviewed: documentation example, not a real finding"
15
15
 
16
16
 
@@ -24,7 +24,7 @@ class RuleHintTests(unittest.TestCase):
24
24
  for rule in ("openai-key", "anthropic-key", "eth-private-key", "wif-key", "bip39-mnemonic"):
25
25
  self.assertIn("rotate", cli.RULE_HINTS["leftblock-" + rule])
26
26
  self.assertIn("relative path", cli.RULE_HINTS["leftblock-home-path-posix"])
27
- self.assertIn("role or placeholder", cli.RULE_HINTS["leftblock-personal-email"])
27
+ self.assertIn("reserved placeholder", cli.RULE_HINTS["leftblock-personal-email"])
28
28
 
29
29
 
30
30
  @unittest.skipUnless(GITLEAKS, "Gitleaks must be installed for actual scanner tests")
@@ -12,8 +12,8 @@ from test_commit_gate import GITLEAKS, RepositoryFixture
12
12
 
13
13
  # Flagged by the shipped personal-email rule; the rule allowlists only
14
14
  # example.* and GitHub identities.
15
- EMAIL = "info" + "@" + "public-role.test"
16
- OTHER_EMAIL = "help" + "@" + "public-role.test"
15
+ EMAIL = "info" + "@" + "public-role" + ".co"
16
+ OTHER_EMAIL = "help" + "@" + "public-role" + ".co"
17
17
  PAGE = "page.tsx"
18
18
  REASON = "Public role address for the site"
19
19
 
@@ -100,7 +100,7 @@ class RecordedOverrideTests(RepositoryFixture):
100
100
  detail = [l for l in proc.stderr.splitlines() if l.startswith(" ")]
101
101
  self.assertEqual(detail, [
102
102
  f" {PAGE}:2: leftblock-personal-email [id {ident}] (Personal email address)",
103
- " Hint: Use a role or placeholder address, or describe it instead.",
103
+ " Hint: Use a role address or a reserved placeholder (example.com/.org/.net, or any .test, .example or .invalid domain), or describe it instead.",
104
104
  ])
105
105
  self.assertIn(f"leftblock-personal-email in {PAGE}:2 [id {ident}]", proc.stderr.splitlines()[-1])
106
106
  self.assertNotIn(EMAIL, proc.stdout + proc.stderr)
@@ -109,7 +109,7 @@ class SensitiveFixtureTests(unittest.TestCase):
109
109
  # Synthetic personal values are assembled at test time so this
110
110
  # test source is itself clean under the shipped ruleset.
111
111
  user = "jd" + "oe"
112
- email = "jane." + "doe@" + "example-corp." + "t" + "est"
112
+ email = "jane." + "doe@" + "example-corp" + ".co"
113
113
  findings = scan_and_rule_ids({
114
114
  "issues/one.json": (
115
115
  '{"assignee_email": "%s", "session_id": "%s",'
@@ -225,14 +225,31 @@ class NegativeTests(unittest.TestCase):
225
225
  def test_no_reply_addresses_pass_but_lookalikes_still_flag(self):
226
226
  at = "@"
227
227
  self.assertEqual(scan_and_rule_ids({"CHANGELOG.md": "\n".join([
228
- "Co-Authored-By: Bot <noreply" + at + "vendor.test>",
229
- "From: no-reply" + at + "vendor.test",
228
+ "Co-Authored-By: Bot <noreply" + at + "vendor" + ".co" + ">",
229
+ "From: no-reply" + at + "vendor" + ".co",
230
230
  ]) + "\n"}), [])
231
- self.assertEqual(scan_and_rule_ids({"notes.md": "mail jo" + at + "vendor.test\n"}),
231
+ self.assertEqual(scan_and_rule_ids({"notes.md": "mail jo" + at + "vendor" + ".co\n"}),
232
232
  ["leftblock-personal-email"])
233
- self.assertEqual(scan_and_rule_ids({"notes.md": "mail notnoreply" + at + "vendor.test\n"}),
233
+ self.assertEqual(scan_and_rule_ids({"notes.md": "mail notnoreply" + at + "vendor" + ".co\n"}),
234
234
  ["leftblock-personal-email"])
235
235
 
236
+ def test_reserved_placeholder_domains_pass_but_lookalikes_still_flag(self):
237
+ at = "@"
238
+ passing = [
239
+ "person" + at + "example.invalid",
240
+ "a" + at + "mail.acme.test",
241
+ "b" + at + "deep.sub.host.example",
242
+ "c" + at + "app.localhost",
243
+ "d" + at + "example.edu",
244
+ "e" + at + "x.test",
245
+ ]
246
+ self.assertEqual(scan_and_rule_ids({"notes.md": "\n".join("mail " + a for a in passing) + "\n"}), [])
247
+ for domain in ["test" + ".com", "invalid" + ".org", "example.test" + ".co", "mytest" + ".dev",
248
+ "example" + ".edu.co", "notexample" + ".edu"]:
249
+ with self.subTest(domain=domain):
250
+ self.assertEqual(scan_and_rule_ids({"notes.md": "mail jo" + at + domain + "\n"}),
251
+ ["leftblock-personal-email"])
252
+
236
253
  def test_public_wallet_addresses_and_hashes_not_flagged(self):
237
254
  rng = _rng()
238
255
  findings = scan_and_rule_ids({
@@ -466,7 +483,7 @@ class KanbusBoardAllowlistTests(unittest.TestCase):
466
483
  scan_and_rule_ids({path: content}))
467
484
 
468
485
  def test_personal_email_home_path_and_key_still_flagged_in_board_files(self):
469
- email = "jane." + "doe@" + "example-corp." + "t" + "est"
486
+ email = "jane." + "doe@" + "example-corp" + ".co"
470
487
  user = "jd" + "oe"
471
488
  cases = {
472
489
  "leftblock-personal-email": json.dumps(
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes