secretshield 0.1.0__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 secretshield contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,297 @@
1
+ Metadata-Version: 2.4
2
+ Name: secretshield
3
+ Version: 0.1.0
4
+ Summary: Detect and redact likely secrets before they reach Python's terminal output or logging system.
5
+ Author: secretshield contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Sam3360/secretshield
8
+ Project-URL: Repository, https://github.com/Sam3360/secretshield
9
+ Project-URL: Issues, https://github.com/Sam3360/secretshield/issues
10
+ Keywords: security,secrets,redaction,logging,stdout,credentials
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Security
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest>=7.0; extra == "dev"
25
+ Dynamic: license-file
26
+
27
+ # secretshield
28
+
29
+ `secretshield` is a local Python security utility that detects likely
30
+ secrets (API keys, tokens, passwords, private keys, and other
31
+ credential-shaped strings) and redacts them **before** they are printed
32
+ through Python's terminal output (`stdout`/`stderr`) or the standard
33
+ `logging` module.
34
+
35
+ ```python
36
+ import secretshield
37
+
38
+ api_key = "sk-example1234567890abcdefFAKEKEY"
39
+ print("API key:", api_key)
40
+ ```
41
+
42
+ ```text
43
+ API key: ********
44
+ ⚠ secretshield: Potential secret detected and redacted.
45
+ ```
46
+
47
+ The real secret value never appears in the redacted output, in
48
+ secretshield's own warning messages, or in any exception it raises.
49
+
50
+ ## Why it exists
51
+
52
+ Secrets end up in terminal output and logs more often than anyone
53
+ intends: a debug `print()` left in accidentally, a stack trace that
54
+ includes a config dict, a `logger.info()` call that dumps request
55
+ headers. `secretshield` is a small, dependency-free safety net for
56
+ exactly that class of mistake during local development and debugging.
57
+
58
+ It is **not** a replacement for secret management, code review, or
59
+ static-analysis security tooling — see [Limitations](#limitations) below.
60
+
61
+ ## Installation
62
+
63
+ ```bash
64
+ pip install secretshield
65
+ ```
66
+
67
+ For local development, from a cloned copy of this repository:
68
+
69
+ ```bash
70
+ pip install -e ".[dev]"
71
+ ```
72
+
73
+ Requires Python 3.10 or newer. No third-party runtime dependencies.
74
+
75
+ ## Basic usage
76
+
77
+ Protection for `sys.stdout`, `sys.stderr`, and `logging` is enabled the
78
+ moment you import the package:
79
+
80
+ ```python
81
+ import secretshield
82
+
83
+ password = "hunter2-example-not-real"
84
+ print("Using password:", password)
85
+ ```
86
+
87
+ ```text
88
+ Using password: ********
89
+ ⚠ secretshield: Potential secret detected and redacted.
90
+ ```
91
+
92
+ You can also toggle protection manually:
93
+
94
+ ```python
95
+ import secretshield
96
+
97
+ secretshield.disable() # protection off
98
+ secretshield.enable() # protection back on (idempotent, safe to call repeatedly)
99
+ secretshield.is_enabled()
100
+ ```
101
+
102
+ ### Detecting or redacting text directly
103
+
104
+ You don't need to route text through stdout/logging to use the
105
+ detection and redaction logic:
106
+
107
+ ```python
108
+ from secretshield import detect, redact
109
+
110
+ matches = detect("aws_key=AKIAABCDEFGHIJKLMNOP")
111
+ # [Match(start=8, end=28, value='AKIA...', kind='aws_access_key_id')]
112
+
113
+ safe_text, was_redacted = redact("aws_key=AKIAABCDEFGHIJKLMNOP")
114
+ # ("aws_key=********", True)
115
+ ```
116
+
117
+ ## Examples
118
+
119
+ See the [`examples/`](examples/) directory:
120
+
121
+ * [`examples/basic.py`](examples/basic.py) — a fake secret printed to
122
+ the terminal.
123
+ * [`examples/logging_demo.py`](examples/logging_demo.py) — a fake secret
124
+ logged via both `%s`-style arguments and an f-string.
125
+
126
+ Run either with:
127
+
128
+ ```bash
129
+ python examples/basic.py
130
+ python examples/logging_demo.py
131
+ ```
132
+
133
+ ## CLI
134
+
135
+ ```bash
136
+ secretshield --help
137
+ secretshield --version
138
+ ```
139
+
140
+ ### `run` — execute a script with runtime protection
141
+
142
+ ```bash
143
+ secretshield run app.py [args...]
144
+ ```
145
+
146
+ Runs `app.py` as `__main__` with `sys.stdout`, `sys.stderr`, and
147
+ `logging` protected for the duration of the script's execution. This is
148
+ useful for wrapping an existing script without editing its source.
149
+
150
+ ### `scan` — static file/directory scanning
151
+
152
+ ```bash
153
+ secretshield scan .
154
+ secretshield scan path/to/file.py
155
+ ```
156
+
157
+ Scans a file, or recursively scans a directory of text-like files
158
+ (`.py`, `.txt`, `.md`, `.env`, `.yml`, `.json`, `.ini`, `.toml`, `.sh`,
159
+ `.js`, `.ts`, etc.), reporting the *kind* and *location* of any likely
160
+ secrets found. `scan` does **not** execute any code and does **not**
161
+ print the secret values themselves — only where they were found. It
162
+ exits with status `1` if anything was found, `0` otherwise, so it can be
163
+ used as a pre-commit or CI check.
164
+
165
+ **`scan` is static analysis; `run` (and the automatic protection on
166
+ import) is runtime redaction.** They are separate features: `scan`
167
+ looks at file contents on disk, `run`/import-time protection looks at
168
+ what a running program actually writes out.
169
+
170
+ ## Configuration
171
+
172
+ ```python
173
+ import secretshield
174
+
175
+ secretshield.configure(
176
+ enabled=True, # master on/off switch
177
+ redact_with="********", # placeholder used in place of a secret
178
+ entropy_threshold=4.2, # bits/char threshold for generic detection
179
+ notify=True, # print the "potential secret" warning
180
+ )
181
+ ```
182
+
183
+ Sensible defaults mean most projects need zero configuration.
184
+
185
+ ## Detection methods
186
+
187
+ `secretshield` combines two strategies:
188
+
189
+ 1. **Known-format pattern matching** — regexes tuned to the shape of
190
+ common credential formats: AWS access keys, GitHub tokens, OpenAI-style
191
+ keys, Slack tokens, Stripe keys, Google API keys, JWTs, bearer tokens,
192
+ PEM-style private-key blocks, and generic `key = value` pairs whose
193
+ label looks like `api_key`, `secret`, `token`, `password`, etc.
194
+ 2. **Generic high-entropy detection** — a Shannon-entropy check over
195
+ long, non-dictionary-like character runs, used to catch random-looking
196
+ secrets that don't match a known format. This is intentionally used
197
+ as a *supplement*, not the primary mechanism, because entropy alone
198
+ produces far too many false positives on things like hashes, UUIDs,
199
+ and encoded binary data that aren't secrets.
200
+
201
+ ## Architecture
202
+
203
+ ```text
204
+ secretshield/
205
+ ├── patterns.py # regexes for known secret formats
206
+ ├── detector.py # detect(): pattern + entropy matching -> Match objects
207
+ ├── redactor.py # redact(): turns Match spans into "********"
208
+ ├── config.py # configure()/get_config(): runtime settings
209
+ ├── notifications.py # safe, secret-free console/desktop warnings
210
+ ├── guardian.py # stdout/stderr wrapping + logging record-factory hook
211
+ └── cli.py # `secretshield` command-line entry point
212
+ ```
213
+
214
+ Key design points:
215
+
216
+ * **Stream wrapping**, not monkey-patching `print`: `sys.stdout` and
217
+ `sys.stderr` are replaced with a thin wrapper object that redacts on
218
+ `write()` and delegates everything else (`flush`, `isatty`, attribute
219
+ access) to the original stream.
220
+ * **Logging protection** hooks `logging.setLogRecordFactory`, not a
221
+ `Filter` on the root logger. Filters attached to the root logger are
222
+ only consulted by the logger that originated a given call, so a
223
+ root-only filter would miss records from `logging.getLogger(__name__)`
224
+ child loggers. The record factory is invoked for every `LogRecord`
225
+ created anywhere in the process, so both `record.msg` (f-strings /
226
+ pre-formatted messages) and `record.args` (`%s`-style lazy arguments)
227
+ are reliably covered regardless of logger hierarchy.
228
+ * **Re-entrancy guards** prevent secretshield's own warning output from
229
+ being fed back into detection/logging and causing recursive loops.
230
+ * Detection and redaction failures are caught and swallowed — a bug in
231
+ secretshield should never crash or block the host application's
232
+ normal output.
233
+
234
+ ## Testing
235
+
236
+ ```bash
237
+ pip install -e ".[dev]"
238
+ pytest
239
+ ```
240
+
241
+ The test suite covers known-token detection, entropy detection, false
242
+ positives, single/multiple/repeated secrets, multiline text, stdout,
243
+ stderr, logging (`%s` args and f-strings), enable/disable idempotency,
244
+ and stream restoration. All secrets used in tests and examples are fake.
245
+
246
+ ## Limitations
247
+
248
+ `secretshield` protects **Python's own `stdout`, `stderr`, and `logging`
249
+ output within the current process.** It is a helpful safety net, not a
250
+ comprehensive security boundary. Specifically, it does **not**:
251
+
252
+ * Prevent secrets from appearing in **screenshots** or screen recordings.
253
+ * Prevent **clipboard** leaks.
254
+ * Prevent secrets written via **arbitrary file writes** (e.g. `open(...).write(...)`,
255
+ `json.dump`, writing to a database).
256
+ * Protect **other applications** or processes outside this Python
257
+ interpreter.
258
+ * Redact output from **arbitrary subprocesses** — only output written
259
+ through this process's own `sys.stdout`/`sys.stderr`/`logging` is
260
+ covered, not everything a spawned subprocess itself prints to its own
261
+ inherited file descriptors before Python sees it.
262
+ * Prevent **network leaks** (secrets sent over HTTP, sockets, etc.).
263
+ * Catch **every possible way** a secret can leave a computer. Detection
264
+ is pattern- and entropy-based and can miss unusual or obfuscated
265
+ formats, and can occasionally over- or under-match.
266
+
267
+ Treat `secretshield` as a defense-in-depth safety net for accidental
268
+ local exposure during development and debugging — not as a substitute
269
+ for proper secret management (vaults, environment isolation, `.gitignore`
270
+ discipline, secret scanning in CI, least-privilege credentials, etc.).
271
+
272
+ ## Security considerations
273
+
274
+ * secretshield performs **no network calls** and collects **no
275
+ telemetry**. All detection and redaction happens locally, in-process.
276
+ * Desktop notifications (if you wire up your own backend beyond the
277
+ built-in best-effort `notify-send`/`osascript` calls) are optional and
278
+ fail silently if unavailable — they never crash the host application.
279
+ * Because detection is heuristic, it can produce false negatives (a real
280
+ secret slips through) or false positives (harmless text gets redacted).
281
+ Tune `entropy_threshold` and, where needed, extend `patterns.py` for
282
+ your own credential formats.
283
+
284
+ ## Contributing
285
+
286
+ Issues and pull requests are welcome. Please:
287
+
288
+ 1. Add tests for any new detection pattern or behavior change.
289
+ 2. Use only fake/example credentials in tests, examples, and docs —
290
+ never real secrets.
291
+ 3. Keep the standard-library-only dependency policy unless there's a
292
+ strong reason to add a dependency, and discuss it in an issue first.
293
+ 4. Run `pytest` before opening a PR.
294
+
295
+ ## License
296
+
297
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,271 @@
1
+ # secretshield
2
+
3
+ `secretshield` is a local Python security utility that detects likely
4
+ secrets (API keys, tokens, passwords, private keys, and other
5
+ credential-shaped strings) and redacts them **before** they are printed
6
+ through Python's terminal output (`stdout`/`stderr`) or the standard
7
+ `logging` module.
8
+
9
+ ```python
10
+ import secretshield
11
+
12
+ api_key = "sk-example1234567890abcdefFAKEKEY"
13
+ print("API key:", api_key)
14
+ ```
15
+
16
+ ```text
17
+ API key: ********
18
+ ⚠ secretshield: Potential secret detected and redacted.
19
+ ```
20
+
21
+ The real secret value never appears in the redacted output, in
22
+ secretshield's own warning messages, or in any exception it raises.
23
+
24
+ ## Why it exists
25
+
26
+ Secrets end up in terminal output and logs more often than anyone
27
+ intends: a debug `print()` left in accidentally, a stack trace that
28
+ includes a config dict, a `logger.info()` call that dumps request
29
+ headers. `secretshield` is a small, dependency-free safety net for
30
+ exactly that class of mistake during local development and debugging.
31
+
32
+ It is **not** a replacement for secret management, code review, or
33
+ static-analysis security tooling — see [Limitations](#limitations) below.
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ pip install secretshield
39
+ ```
40
+
41
+ For local development, from a cloned copy of this repository:
42
+
43
+ ```bash
44
+ pip install -e ".[dev]"
45
+ ```
46
+
47
+ Requires Python 3.10 or newer. No third-party runtime dependencies.
48
+
49
+ ## Basic usage
50
+
51
+ Protection for `sys.stdout`, `sys.stderr`, and `logging` is enabled the
52
+ moment you import the package:
53
+
54
+ ```python
55
+ import secretshield
56
+
57
+ password = "hunter2-example-not-real"
58
+ print("Using password:", password)
59
+ ```
60
+
61
+ ```text
62
+ Using password: ********
63
+ ⚠ secretshield: Potential secret detected and redacted.
64
+ ```
65
+
66
+ You can also toggle protection manually:
67
+
68
+ ```python
69
+ import secretshield
70
+
71
+ secretshield.disable() # protection off
72
+ secretshield.enable() # protection back on (idempotent, safe to call repeatedly)
73
+ secretshield.is_enabled()
74
+ ```
75
+
76
+ ### Detecting or redacting text directly
77
+
78
+ You don't need to route text through stdout/logging to use the
79
+ detection and redaction logic:
80
+
81
+ ```python
82
+ from secretshield import detect, redact
83
+
84
+ matches = detect("aws_key=AKIAABCDEFGHIJKLMNOP")
85
+ # [Match(start=8, end=28, value='AKIA...', kind='aws_access_key_id')]
86
+
87
+ safe_text, was_redacted = redact("aws_key=AKIAABCDEFGHIJKLMNOP")
88
+ # ("aws_key=********", True)
89
+ ```
90
+
91
+ ## Examples
92
+
93
+ See the [`examples/`](examples/) directory:
94
+
95
+ * [`examples/basic.py`](examples/basic.py) — a fake secret printed to
96
+ the terminal.
97
+ * [`examples/logging_demo.py`](examples/logging_demo.py) — a fake secret
98
+ logged via both `%s`-style arguments and an f-string.
99
+
100
+ Run either with:
101
+
102
+ ```bash
103
+ python examples/basic.py
104
+ python examples/logging_demo.py
105
+ ```
106
+
107
+ ## CLI
108
+
109
+ ```bash
110
+ secretshield --help
111
+ secretshield --version
112
+ ```
113
+
114
+ ### `run` — execute a script with runtime protection
115
+
116
+ ```bash
117
+ secretshield run app.py [args...]
118
+ ```
119
+
120
+ Runs `app.py` as `__main__` with `sys.stdout`, `sys.stderr`, and
121
+ `logging` protected for the duration of the script's execution. This is
122
+ useful for wrapping an existing script without editing its source.
123
+
124
+ ### `scan` — static file/directory scanning
125
+
126
+ ```bash
127
+ secretshield scan .
128
+ secretshield scan path/to/file.py
129
+ ```
130
+
131
+ Scans a file, or recursively scans a directory of text-like files
132
+ (`.py`, `.txt`, `.md`, `.env`, `.yml`, `.json`, `.ini`, `.toml`, `.sh`,
133
+ `.js`, `.ts`, etc.), reporting the *kind* and *location* of any likely
134
+ secrets found. `scan` does **not** execute any code and does **not**
135
+ print the secret values themselves — only where they were found. It
136
+ exits with status `1` if anything was found, `0` otherwise, so it can be
137
+ used as a pre-commit or CI check.
138
+
139
+ **`scan` is static analysis; `run` (and the automatic protection on
140
+ import) is runtime redaction.** They are separate features: `scan`
141
+ looks at file contents on disk, `run`/import-time protection looks at
142
+ what a running program actually writes out.
143
+
144
+ ## Configuration
145
+
146
+ ```python
147
+ import secretshield
148
+
149
+ secretshield.configure(
150
+ enabled=True, # master on/off switch
151
+ redact_with="********", # placeholder used in place of a secret
152
+ entropy_threshold=4.2, # bits/char threshold for generic detection
153
+ notify=True, # print the "potential secret" warning
154
+ )
155
+ ```
156
+
157
+ Sensible defaults mean most projects need zero configuration.
158
+
159
+ ## Detection methods
160
+
161
+ `secretshield` combines two strategies:
162
+
163
+ 1. **Known-format pattern matching** — regexes tuned to the shape of
164
+ common credential formats: AWS access keys, GitHub tokens, OpenAI-style
165
+ keys, Slack tokens, Stripe keys, Google API keys, JWTs, bearer tokens,
166
+ PEM-style private-key blocks, and generic `key = value` pairs whose
167
+ label looks like `api_key`, `secret`, `token`, `password`, etc.
168
+ 2. **Generic high-entropy detection** — a Shannon-entropy check over
169
+ long, non-dictionary-like character runs, used to catch random-looking
170
+ secrets that don't match a known format. This is intentionally used
171
+ as a *supplement*, not the primary mechanism, because entropy alone
172
+ produces far too many false positives on things like hashes, UUIDs,
173
+ and encoded binary data that aren't secrets.
174
+
175
+ ## Architecture
176
+
177
+ ```text
178
+ secretshield/
179
+ ├── patterns.py # regexes for known secret formats
180
+ ├── detector.py # detect(): pattern + entropy matching -> Match objects
181
+ ├── redactor.py # redact(): turns Match spans into "********"
182
+ ├── config.py # configure()/get_config(): runtime settings
183
+ ├── notifications.py # safe, secret-free console/desktop warnings
184
+ ├── guardian.py # stdout/stderr wrapping + logging record-factory hook
185
+ └── cli.py # `secretshield` command-line entry point
186
+ ```
187
+
188
+ Key design points:
189
+
190
+ * **Stream wrapping**, not monkey-patching `print`: `sys.stdout` and
191
+ `sys.stderr` are replaced with a thin wrapper object that redacts on
192
+ `write()` and delegates everything else (`flush`, `isatty`, attribute
193
+ access) to the original stream.
194
+ * **Logging protection** hooks `logging.setLogRecordFactory`, not a
195
+ `Filter` on the root logger. Filters attached to the root logger are
196
+ only consulted by the logger that originated a given call, so a
197
+ root-only filter would miss records from `logging.getLogger(__name__)`
198
+ child loggers. The record factory is invoked for every `LogRecord`
199
+ created anywhere in the process, so both `record.msg` (f-strings /
200
+ pre-formatted messages) and `record.args` (`%s`-style lazy arguments)
201
+ are reliably covered regardless of logger hierarchy.
202
+ * **Re-entrancy guards** prevent secretshield's own warning output from
203
+ being fed back into detection/logging and causing recursive loops.
204
+ * Detection and redaction failures are caught and swallowed — a bug in
205
+ secretshield should never crash or block the host application's
206
+ normal output.
207
+
208
+ ## Testing
209
+
210
+ ```bash
211
+ pip install -e ".[dev]"
212
+ pytest
213
+ ```
214
+
215
+ The test suite covers known-token detection, entropy detection, false
216
+ positives, single/multiple/repeated secrets, multiline text, stdout,
217
+ stderr, logging (`%s` args and f-strings), enable/disable idempotency,
218
+ and stream restoration. All secrets used in tests and examples are fake.
219
+
220
+ ## Limitations
221
+
222
+ `secretshield` protects **Python's own `stdout`, `stderr`, and `logging`
223
+ output within the current process.** It is a helpful safety net, not a
224
+ comprehensive security boundary. Specifically, it does **not**:
225
+
226
+ * Prevent secrets from appearing in **screenshots** or screen recordings.
227
+ * Prevent **clipboard** leaks.
228
+ * Prevent secrets written via **arbitrary file writes** (e.g. `open(...).write(...)`,
229
+ `json.dump`, writing to a database).
230
+ * Protect **other applications** or processes outside this Python
231
+ interpreter.
232
+ * Redact output from **arbitrary subprocesses** — only output written
233
+ through this process's own `sys.stdout`/`sys.stderr`/`logging` is
234
+ covered, not everything a spawned subprocess itself prints to its own
235
+ inherited file descriptors before Python sees it.
236
+ * Prevent **network leaks** (secrets sent over HTTP, sockets, etc.).
237
+ * Catch **every possible way** a secret can leave a computer. Detection
238
+ is pattern- and entropy-based and can miss unusual or obfuscated
239
+ formats, and can occasionally over- or under-match.
240
+
241
+ Treat `secretshield` as a defense-in-depth safety net for accidental
242
+ local exposure during development and debugging — not as a substitute
243
+ for proper secret management (vaults, environment isolation, `.gitignore`
244
+ discipline, secret scanning in CI, least-privilege credentials, etc.).
245
+
246
+ ## Security considerations
247
+
248
+ * secretshield performs **no network calls** and collects **no
249
+ telemetry**. All detection and redaction happens locally, in-process.
250
+ * Desktop notifications (if you wire up your own backend beyond the
251
+ built-in best-effort `notify-send`/`osascript` calls) are optional and
252
+ fail silently if unavailable — they never crash the host application.
253
+ * Because detection is heuristic, it can produce false negatives (a real
254
+ secret slips through) or false positives (harmless text gets redacted).
255
+ Tune `entropy_threshold` and, where needed, extend `patterns.py` for
256
+ your own credential formats.
257
+
258
+ ## Contributing
259
+
260
+ Issues and pull requests are welcome. Please:
261
+
262
+ 1. Add tests for any new detection pattern or behavior change.
263
+ 2. Use only fake/example credentials in tests, examples, and docs —
264
+ never real secrets.
265
+ 3. Keep the standard-library-only dependency policy unless there's a
266
+ strong reason to add a dependency, and discuss it in an issue first.
267
+ 4. Run `pytest` before opening a PR.
268
+
269
+ ## License
270
+
271
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,46 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "secretshield"
7
+ version = "0.1.0"
8
+ description = "Detect and redact likely secrets before they reach Python's terminal output or logging system."
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "secretshield contributors" },
14
+ ]
15
+ keywords = ["security", "secrets", "redaction", "logging", "stdout", "credentials"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Topic :: Security",
25
+ "Topic :: Software Development :: Libraries :: Python Modules",
26
+ ]
27
+ dependencies = []
28
+
29
+ [project.optional-dependencies]
30
+ dev = [
31
+ "pytest>=7.0",
32
+ ]
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/Sam3360/secretshield"
36
+ Repository = "https://github.com/Sam3360/secretshield"
37
+ Issues = "https://github.com/Sam3360/secretshield/issues"
38
+
39
+ [project.scripts]
40
+ secretshield = "secretshield.cli:main"
41
+
42
+ [tool.setuptools.packages.find]
43
+ include = ["secretshield*"]
44
+
45
+ [tool.pytest.ini_options]
46
+ testpaths = ["tests"]
@@ -0,0 +1,44 @@
1
+ """
2
+ secretshield: detect and redact likely secrets before they reach
3
+ Python's terminal output or logging system.
4
+
5
+ Importing this package automatically enables protection for
6
+ ``sys.stdout``, ``sys.stderr``, and the standard ``logging`` module::
7
+
8
+ import secretshield
9
+
10
+ api_key = "example-secret-value"
11
+ print("API key:", api_key)
12
+ # API key: ********
13
+ # \u26a0 secretshield: Potential secret detected and redacted.
14
+
15
+ Protection can be toggled manually with :func:`enable` / :func:`disable`,
16
+ and behavior can be tuned with :func:`configure`.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from .config import Config, configure, get_config, reset_config
22
+ from .detector import Match, detect
23
+ from .guardian import disable, enable, is_enabled
24
+ from .redactor import redact
25
+
26
+ __version__ = "0.1.0"
27
+
28
+ __all__ = [
29
+ "__version__",
30
+ "enable",
31
+ "disable",
32
+ "is_enabled",
33
+ "configure",
34
+ "get_config",
35
+ "reset_config",
36
+ "Config",
37
+ "detect",
38
+ "redact",
39
+ "Match",
40
+ ]
41
+
42
+ # Automatically protect stdout/stderr/logging as soon as secretshield is
43
+ # imported, per the tool's core promise: "import it and you're protected."
44
+ enable()