Skip to content

Allow plugins to customize taint issue messages and attach metadata (e.g. CWE IDs) #11762

@alies-dev

Description

@alies-dev

Problem

When a plugin registers taint sinks via TaintFlowGraph::addSink(), the resulting issue message is hardcoded per taint type in TaintFlowGraph::connectSinksAndSources():

TaintKind::USER_SECRET => new TaintedUserSecret(
    'Detected tainted user secret leaking',
    // ...
),

There is no way for a plugin to:

  1. Customize the issue message for a specific sink (e.g. to explain why the sink is dangerous)
  2. Attach metadata like a CWE identifier

Use Case

In psalm-plugin-laravel#576, we added a handler that detects timing-unsafe comparisons of secrets (CWE-208). The handler adds USER_SECRET | SYSTEM_SECRET taint sinks at ===, ==, strcmp(), and strcasecmp() expressions. When a secret-tainted value flows into one of these, Psalm reports:

TaintedUserSecret: Detected tainted user secret leaking

This is technically correct but misleading — the issue is a timing attack vulnerability, not a secret leak. We'd like to report something like:

TaintedUserSecret: Timing-unsafe comparison of secret — use hash_equals() for constant-time comparison (CWE-208)

Current Workarounds

  • Custom taint type → emits TaintedCustom("Detected tainted <name>"). Slightly better but users can't suppress it independently from other TaintedCustom issues, and there's still no CWE field.
  • Direct PluginIssue emission → allows custom messages but loses taint flow tracking entirely (taint resolution runs after expression analysis).

Suggestion

Allow DataFlowNode (or the sink registration API) to carry an optional message override and/or metadata that gets used when the taint resolution emits the issue. For example:

$sink = DataFlowNode::make($id, $label, $location, null, $taints);
// hypothetical API:
$sink = $sink->withMessage('Timing-unsafe comparison — use hash_equals()');

Or a more structured approach with CWE support on CodeIssue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions