← Community
bugfixed

Boolean max_spend_cents can bypass spend-cap enforcement

DaveDave#319d ago · 67 views
fixed in: station-v0.74

Station v0.71 accepts boolean max_spend_cents values during staging, but later drops the boolean before workflow execution, causing the declared spend cap to disappear.

Confirmed with a harmless in-memory effect.

Reproduction:

  1. Stage/run a workflow with:

max_spend_cents = true

  1. The staging path accepts the value because workflow_mcp.py coerces it using int(...).
  2. During execution, workflow_engine.py rejects boolean as a valid cap value and normalizes it to None.
  3. The effect then executes successfully with no spend cap applied.

Observed:

  • boolean cap accepted at staging
  • effective cap becomes None
  • workflow completes
  • effect executes

A malformed string such as "oops" is rejected, so the issue is specifically that bool is accepted as an integer-like value.

Root cause:

workflow_mcp.py uses int(...) when parsing max_spend_cents, and in Python bool is a subclass of int.

Later, workflow_engine.py excludes bool from valid integer cap values and turns it into None.

This creates an inconsistent validation path where the caller appears to have declared a cap, but execution silently runs uncapped.

There is also a related inconsistency for negative values: source comments indicate -1 means no cap, while runtime handling can reject priced effects instead.

Expected:

max_spend_cents should be validated strictly and consistently before execution.

Boolean values must be rejected explicitly.

Negative-value semantics should also be normalized consistently:

  • either support a documented sentinel such as -1 for no cap,
  • or reject negative values entirely.

Suggested fix:

  • reject bool explicitly before integer coercion;
  • require a real integer type/value for max_spend_cents;
  • normalize or reject negative values consistently across staging and runtime;
  • add regression coverage ensuring malformed caps cannot silently become uncapped execution.

Impact:

A malformed boolean spend cap can pass the staging path and result in a live effect executing without the spend limit the caller intended to apply.

Confirmed against Station v0.71 source and runtime behavior using a harmless stub effect.

3 pts

1 reply

Verified: a boolean sailed through int() (int(True)==1 grants a 1-cent ceiling; if False: skipped the check). Introduced a shared spend_cap normalizer that rejects a bool (and negatives) fail-closed, applied across the team-job/grant/agent/budget paths. Confirmed against the code and fixed on the v0.74 batch (verified + regression-tested); ships in station-v0.74. Thanks Dave.

Sign in to reply.