Skip to content

Treat an unreadable __artifacts_v2__ as a sink, not as a non-sink - #396

Merged
abrignoni merged 1 commit into
mainfrom
fix/checker-fail-safe-sink
Aug 7, 2026
Merged

Treat an unreadable __artifacts_v2__ as a sink, not as a non-sink#396
abrignoni merged 1 commit into
mainfrom
fix/checker-fail-safe-sink

Conversation

@abrignoni

Copy link
Copy Markdown
Owner

The hole

A module whose __artifacts_v2__ is built by a helper cannot be evaluated statically, so declares_html_columns() returns None. is_sink read that as falsy:

is_sink = bool(declares) or uses_media_helper(tree) or in_scope_functions

So the module was skipped by all three rules — not just by unguarded-html-columns, which is the only one that actually needs the declaration.

That is fail-open in the one case where the answer is unknown. A module in the NOT CHECKED list could gain an html_columns tomorrow and stay completely unguarded, with nothing in the output changing to say so.

The fix

An unreadable declaration is now treated as a sink. The uncertainty costs coverage of one rule instead of all three.

Proof it does something

A probe artifact whose __artifacts_v2__ is helper-built, carrying both an unescaped interpolation and a remote <img src>:

findings
old behaviour 0
this change 3

Proof it costs nothing

Measured before committing: no module currently in any core's NOT CHECKED list produces a finding under the new default. No new baseline entries, no allowlist growth.

Checked the other way too — of the eleven such modules across the cores, ten declare no html_columns at runtime, and the eleventh (RLEAPP kikReturns) was already being scanned through a media helper. The hole was latent, not live.

The NOT CHECKED banner now states that the other two rules still run, so the list reads as one missing rule rather than as an unscanned module.

Validation

  • pylint --disable=C,R = 10.00; lint_changed reports no new warnings
  • unit tests OK; the check still exits 0 on this tree

🤖 Generated with Claude Code

A module whose __artifacts_v2__ is built by a helper cannot be evaluated
statically, so declares_html_columns() returns None. is_sink read that as
falsy, which meant the module was skipped by all three rules -- not just by
unguarded-html-columns, which is the only one that actually needs the
declaration.

That is fail-open in the one case where the answer is unknown. A module in the
NOT CHECKED list could gain an html_columns tomorrow and stay completely
unguarded, with nothing in the output changing to say so.

Now an unreadable declaration is treated as a sink. The uncertainty costs
coverage of one rule instead of all three.

Verified against a probe artifact whose __artifacts_v2__ is helper-built and
which carries both an unescaped interpolation and a remote <img src>: the old
behaviour reported 0 findings for it, this reports 3.

Measured before committing: no module currently in any core's NOT CHECKED list
produces a finding under the new default, so this costs nothing today. It was
checked the other way too -- of the eleven such modules across the cores, ten
declare no html_columns at runtime and the eleventh (RLEAPP kikReturns) was
already being scanned through a media helper. The hole was latent, not live.

The NOT CHECKED banner now says the other two rules still run, so the list
reads as one missing rule rather than as an unscanned module.

Validated: pylint --disable=C,R = 10.00; lint_changed reports no new warnings;
unit tests OK; the check still exits 0 on this tree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@abrignoni
abrignoni merged commit fc2e368 into main Aug 7, 2026
1 check passed
@abrignoni
abrignoni deleted the fix/checker-fail-safe-sink branch August 7, 2026 03:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant