|
Option C Tools
|
Functions | |
| bool | _name_matches_secret (str name, *, str mode="substring") |
| bool | _is_string_literal (ast.expr node) |
| tuple[bool, str] | _is_string_like (ast.expr node) |
| float | _shannon_entropy (str s) |
| set[int] | _collect_docstring_node_ids (ast.Module tree) |
| set[int] | _collect_keyword_excluded_node_ids (ast.Module tree, list[str] field_patterns) |
| list[tuple[int, str, float]] | _check_entropy_violations (ast.Module tree, *, float threshold=_ENTROPY_DEFAULT_THRESHOLD, float docstring_threshold=_DOCSTRING_ENTROPY_DEFAULT, float comment_threshold=_COMMENT_ENTROPY_DEFAULT, int min_length=_ENTROPY_MIN_LENGTH, frozenset[int] excluded_node_ids=frozenset()) |
| tuple[bool, str] | check_no_hardcoded_secrets (str text, ast.Module|None tree=None, *, str mode="substring", float code_entropy_threshold=_ENTROPY_DEFAULT_THRESHOLD, float docstring_entropy_threshold=_DOCSTRING_ENTROPY_DEFAULT, float comment_entropy_threshold=_COMMENT_ENTROPY_DEFAULT, list[str]|None excluded_field_patterns=None) |
Variables | |
| _CAMEL_SPLIT_RE = re.compile(r"(?<=[a-z0-9])(?=[A-Z])") | |
| dict | _SECRET_NAME_PATTERNS |
| float | _ENTROPY_DEFAULT_THRESHOLD = 4.5 |
| float | _DOCSTRING_ENTROPY_DEFAULT = 5.0 |
| float | _COMMENT_ENTROPY_DEFAULT = 5.0 |
| int | _ENTROPY_MIN_LENGTH = 16 |
Purpose
-------
OI-514 — standalone hardcoded-secret detection. Extracted from
:mod:`oct.linter.oct_lint` so :mod:`oct.tools.source_exporter`,
:mod:`oct.git.quality_gate`, and any future AI review tools no longer
need to import the linter just to reach the scanner.
The linter continues to re-export the same names for backwards
compatibility — call sites that already import them from
``oct.linter.oct_lint`` keep working unchanged.
Responsibilities
----------------
- Host :data:`_SECRET_NAME_PATTERNS` — the canonical set of substrings
that flag a variable/parameter/key name as "secret-shaped".
- Provide :func:`_name_matches_secret` for substring matching.
- Provide :func:`check_no_hardcoded_secrets` — the AST-based scanner.
- Provide :func:`_is_string_literal` / :func:`_is_string_like` helpers.
Diagnostics
-----------
Domain: SECRET-SCAN
Levels:
L2 — scan lifecycle (start / end)
L3 — pattern hits (per-line matches)
L4 — AST walk details
Contracts
---------
- Must not import :mod:`oct.linter.oct_lint` (no circular dependency).
- Function signatures and return shapes are stable — the linter
re-exports them, so any change here is a breaking change there.
- Name patterns are case-insensitive substring matches.
|
protected |
Walk AST for string constants exceeding the entropy threshold. Returns a list of ``(lineno, value_preview, entropy_bits)`` tuples. Only strings longer than *min_length* are checked. The preview is truncated to 24 characters for readability. Code strings use ``>=`` (catches at threshold). Docstrings use strict ``>`` (must exceed threshold). ``comment_threshold`` is accepted for forward compatibility but not yet consumed — comments do not appear in the AST. Nodes whose ``id()`` is in *excluded_node_ids* are skipped entirely (field-name exclusions from octrc ``entropy_exclusions``).
Definition at line 192 of file secret_scanner.py.
|
protected |
Return ``id()`` values of ast.Constant nodes that are docstrings.
Definition at line 153 of file secret_scanner.py.
|
protected |
Return ``id()`` values of ast.Constant nodes that are keyword arguments with names matching *field_patterns*. This identifies strings like ``correct_pattern="..."`` in ``RuleInfo(correct_pattern="...")`` calls — documentation/example fields in namedtuple/dataclass constructors.
Definition at line 167 of file secret_scanner.py.
|
protected |
Return ``(is_string_like, kind)`` for use by :func:`check_no_hardcoded_secrets`. ``kind`` is one of ``"literal"``, ``"f-string"``, or ``"concatenation"`` (OI-408). Extended detection catches f-strings and ``"a" + "b"`` patterns in addition to plain string constants.
Definition at line 111 of file secret_scanner.py.
|
protected |
True when the AST node is a string constant (hardcoded literal).
Definition at line 106 of file secret_scanner.py.
|
protected |
Return True when ``name`` looks secret-shaped. OI-529: two matching strategies are supported. ``mode="substring"`` (default, back-compat) — any pattern that appears anywhere inside ``name.lower()`` flags the name. This is strict but noisy: ``tokenizer`` (contains ``token``), ``pwdistance`` (contains ``pwd``), etc. all flag. ``mode="word"`` — camelCase boundaries are converted to underscores (``apiKey`` → ``api_Key``), the name is lowercased, and each pattern must appear delimited by start-of-string, end-of-string, ``_``, or ``-`` — so compound patterns like ``api_key`` still match when the original was ``apiKey`` or ``api-key``. Whole-segment hits still flag (``user_password``) but false positives like ``tokenizer`` and ``pwdistance`` pass clean.
Definition at line 75 of file secret_scanner.py.
|
protected |
Return the Shannon entropy (bits per character) of *s*. H = -sum(p * log2(p)) for each unique character's frequency p. Returns 0.0 for empty strings.
Definition at line 140 of file secret_scanner.py.
| tuple[bool, str] secret_scanner.check_no_hardcoded_secrets | ( | str | text, |
| ast.Module | None | tree = None, | ||
| * | , | ||
| str | mode = "substring", | ||
| float | code_entropy_threshold = _ENTROPY_DEFAULT_THRESHOLD, | ||
| float | docstring_entropy_threshold = _DOCSTRING_ENTROPY_DEFAULT, | ||
| float | comment_entropy_threshold = _COMMENT_ENTROPY_DEFAULT, | ||
| list[str] | None | excluded_field_patterns = None ) |
Detect string literals bound to secret-shaped names and high-entropy strings.
Inspects three AST shapes for name-based detection:
* Direct/annotated assignments — ``password = "literal"``.
* Dict literals — ``{"api_key": "literal"}``.
* Function default arguments — ``def f(token="literal"): ...``.
Safe patterns are ignored — calls, subscripts, env lookups.
FS-507: when *code_entropy_threshold* > 0, also flags any string literal
whose Shannon entropy exceeds the threshold (default 4.5 bits/char).
Code strings use ``>=``; docstrings use strict ``>``.
Set to 0 to disable entropy checking.
*docstring_entropy_threshold* (default 5.0) sets the bar for
docstring constants. *comment_entropy_threshold* (default 5.0) is
accepted for forward compatibility but not yet consumed.
OI-529: ``mode`` forwards to :func:`_name_matches_secret`. Default
is ``"substring"`` (legacy behaviour). Pass ``mode="word"`` for
segment-aware matching that avoids false positives like
``compass``/``tokenizer``.
OI-540: *excluded_field_patterns* lists keyword-argument names
(e.g. ``["correct_pattern", "example"]``) whose string values are
exempt from entropy scanning — documentation fields in
namedtuple/dataclass constructors.
Returns ``(passed, detail_message)``; ``passed`` is False when at least
one violation is found.
Definition at line 241 of file secret_scanner.py.
|
protected |
Definition at line 57 of file secret_scanner.py.
|
protected |
Definition at line 136 of file secret_scanner.py.
|
protected |
Definition at line 135 of file secret_scanner.py.
|
protected |
Definition at line 134 of file secret_scanner.py.
|
protected |
Definition at line 137 of file secret_scanner.py.
|
protected |
Definition at line 64 of file secret_scanner.py.