[Connector-linter]: add VC3xx code checks [3/4]#6291
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## feat/connector-linter-1-foundation #6291 +/- ##
======================================================================
- Coverage 26.73% 26.73% -0.01%
======================================================================
Files 1777 1777
Lines 104322 104322
======================================================================
- Hits 27892 27891 -1
- Misses 76430 76431 +1 📢 Thoughts on this report? Let us know! 🚀 New features to boost your workflow:
|
27ad06d to
58e4362
Compare
f8c5e15 to
2f39cd9
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds the VC3xx “code quality” ruleset to the shared/connector_linter tool, introducing a set of static checks (regex + AST-based) that validate common connector implementation patterns (author handling, STIX ID determinism, scheduling/work lifecycle, playbook compatibility, etc.).
Changes:
- Added VC301–VC324 checks implementing code-quality validation for connectors (type-scoped where applicable).
- Introduced shared VC3xx helper utilities for reading sources and performing AST/regex analyses.
- Added VC3xx package initializer documenting the new rule catalog.
Reviewed changes
Copilot reviewed 25 out of 25 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| shared/connector_linter/connector_linter/checks/vc3xx_code/init.py | VC3xx rule catalog / documentation entrypoint. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/_helpers.py | Shared AST/regex/source-loading helpers used across VC3xx checks. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc301_author_defined.py | Checks that an author identity is defined. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc302_author_referenced.py | Checks that author is referenced on entities (created_by_ref/author kwargs). |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc303_connector_type.py | Checks CONNECTOR_TYPE is hardcoded (not read from env). |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc304_markings_checked.py | Checks TLP max enforcement call exists for enrichment connectors. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc305_sdk_base_settings.py | Checks connectors-sdk BaseConnectorSettings adoption / legacy config anti-patterns. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc306_log_level_default.py | Checks log level defaults to error (advisory). |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc307_except_logging.py | Warns on low-severity logging as the only log in except blocks. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc308_main_traceback.py | Enforces main.py guard + traceback-based error handling. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc309_absolute_imports.py | Rejects relative imports in connector source. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc310_external_references.py | Prevents spreading default external refs to non-Identity entities. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc311_tlp_markings.py | Warns if TLP markings are missing/likely inappropriate based on manifest heuristics. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc312_cleanup_bundle.py | Enforces cleanup_inconsistent_bundle=True on send_stix2_bundle calls. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc313_pycti_generate_id.py | Enforces explicit id= for stix2 SDO/SRO constructors unless exempted. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc314_auto_backpressure.py | Enforces schedule_* usage and flags while True loops for external-import connectors. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc315_work_initiated.py | Requires initiate_work (scope currently EXTERNAL_IMPORT). |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc316_work_closed.py | Requires work closure via to_processed (scope EXTERNAL_IMPORT). |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc317_initiate_work_conditional.py | Heuristic warning if initiate_work appears unguarded by conditionals. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc318_helper_listen.py | Enforces helper.listen() usage for enrichment connectors. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc319_scope_fallback.py | Warns if out-of-scope playbook triggers may not return original bundle. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc320_tlp_access_control.py | Enforces full TLP access-control flow (extract + check + reject). |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc321_playbook_compatible.py | Checks playbook_compatible=True and warns if send_stix2_bundle absent. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc322_former_bundle.py | Requires reading data['stix_objects'] for enrichment connectors. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc323_helper_listen_stream.py | Enforces helper.listen_stream() usage for stream connectors. |
| shared/connector_linter/connector_linter/checks/vc3xx_code/vc324_relationship_start_stop.py | Warns when Relationship sets both start_time and stop_time (perf risk). |
2f39cd9 to
21f5d13
Compare
58e4362 to
1b2f047
Compare
21f5d13 to
c9e7378
Compare
7472997 to
f87af77
Compare
6ce204b to
8f91f16
Compare
60f90a0 to
0af460b
Compare
8f91f16 to
c944093
Compare
0af460b to
7623182
Compare
c944093 to
5d497b6
Compare
5bfe52d to
70e89e3
Compare
5d497b6 to
3adb479
Compare
70e89e3 to
3d79991
Compare
acd7987 to
6b60cbd
Compare
3d79991 to
d6acd47
Compare
6b60cbd to
f3f6af7
Compare
d6acd47 to
84090f5
Compare
f3f6af7 to
fcf13fd
Compare
84090f5 to
4d12e30
Compare
Powlinett
left a comment
There was a problem hiding this comment.
Not all my comments are blocking but I think we should fix the check of the ID generation (blocking for custom observables) 🙂
| return [ | ||
| CheckFinding( | ||
| message="Connector type hardcoded", | ||
| severity=Severity.WARNING, |
There was a problem hiding this comment.
If it's accepted, should it emit a warning? Why not just info?
There was a problem hiding this comment.
Warning because using the SDK is the best practice, here it is more "legacy but acceptable"
| return [ | ||
| CheckFinding( | ||
| message="Connector type hardcoded via Pydantic field", | ||
| severity=Severity.WARNING, |
There was a problem hiding this comment.
If it's accepted, should it emit a warning? Why not just info?
There was a problem hiding this comment.
Is this check related to the issue we had on Checkfirst? If yes, then the issue occurs even with start_time set only (no need to set both start_time and stop_time).
Maybe instead of checking whether these arguments are set, we could filter relationship types that shouldn't be "time windowed".
46b2e32 to
4aa1e11
Compare
ab3d7fb to
efe50de
Compare
650763f to
3c95b02
Compare
4aa1e11 to
9a8f9af
Compare
c930d1c
into
feat/connector-linter-1-foundation
Proposed changes
Related issues
Checklist
Further comments
Stacked PR series: