Skip to content

Instantly share code, notes, and snippets.

@panchicore
Last active February 26, 2026 21:36
Show Gist options
  • Select an option

  • Save panchicore/b90c461a12de995557b284dc58f53923 to your computer and use it in GitHub Desktop.

Select an option

Save panchicore/b90c461a12de995557b284dc58f53923 to your computer and use it in GitHub Desktop.

Missing Dependency Check on Artifact (Finding) Custom Field Deletion

Summary

Deleting an Artifact Field (finding custom field) skips dependency checking entirely. A user can delete a field that is actively referenced in workflow nodes, breaking running executions. Model Fields have full dependency protection; Artifact Fields have none.

Impact (prod data — vmprod_17feb)

Metric Count
Active finding workflows 44
Finding workflows using custom_fields.finding.* in source 28
Organizations with finding custom fields defined 30 / 122
Active/waiting/scheduled finding executions 209

Any of the 28 workflows referencing finding custom fields are vulnerable. Deleting a referenced field silently breaks workflow execution — run_save_fields, validate_form, and branch conditions that reference the deleted key will fail at runtime.

Root Cause

The CustomFieldsManager component renders two different delete modals based on type:

// frontend/src/components/CustomFieldsManager/index.tsx:1719-1737

// Artifact Fields — bare "Are you sure?" confirmation, NO dependency check
{type !== 'models' && (
  <ConfirmationAlert
    title={`Deleting field: ${deleteKeyModalOpen}`}
    dialogBody={'Are you sure?'}
    ...
  />
)}

// Model Fields — full dependency check with blocking
{type === 'models' && (
  <ModelCustomFieldDeleteModal .../>  // calls GET /inventory-models/schema/{key}/dependencies
)}

What Model Fields have (and Artifact Fields don't)

Backend:

  • InventoryModelSchema.get_usage(key) → returns {calculation_fields, workflows, finding_type_configs}
  • InventoryModelSchema.get_usage_in_workflows(key) → scans latest version source for custom_fields.model.{key} references
  • GET /api/v1/inventory-models/schema/{key}/dependencies endpoint

Frontend:

  • ModelCustomFieldDeleteModal calls the dependency endpoint
  • Shows dependent workflows as blocking resources (delete button disabled)
  • Shows dependent calculation fields as blocking
  • Shows finding type configs as informational warning

FindingSchema has none of this:

  • No get_usage() method
  • No get_usage_in_workflows() method
  • No /findings/schema/{key}/dependencies endpoint
  • Frontend just shows "Are you sure?"

Files Involved

File Role
backend/src/backend/db/model_inventory.py InventoryModelSchema.get_usage_in_workflows() — exists for models
backend/src/backend/db/finding_schema.py FindingSchema — missing get_usage* methods
backend/src/backend/db/base_schema.py BaseSchemaMixin — defines key_model_prefix / key_base_path
backend/src/backend/routes/internal/inventory_models.py:1004 /schema/{key}/dependencies — model only
frontend/src/components/CustomFieldsManager/index.tsx:1719 Branching: type !== 'models' gets no check
frontend/src/components/ModelCustomFieldDeleteModal/index.tsx Full dependency modal — model only

Suggested Fix

  1. Lift get_usage() and get_usage_in_workflows() to BaseSchemaMixin — use self.key_base_path (custom_fields.model or custom_fields.finding) instead of hardcoding custom_fields.model.{key}
  2. Add GET /findings/schema/{key}/dependencies endpoint mirroring the model one
  3. Rename ModelCustomFieldDeleteModalCustomFieldDeleteModal and make it accept a type prop that determines which API to call
  4. Remove the type !== 'models' branch in CustomFieldsManager — all types use the dependency-aware modal

Namespace Reference

The custom_fields prefix pattern is defined by BaseSchemaMixin.key_base_path:

# base_schema.py:302-304
@property
def key_base_path(self):
    return f"custom_fields.{self.key_model_prefix}"
Schema key_model_prefix Full path in workflow source
InventoryModelSchema "model" custom_fields.model.{key}
FindingSchema "finding" custom_fields.finding.{key}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment